Создание специализированных элементов управления параметрами (Parameter Controls) в ASP.NET 2.0

ОГЛАВЛЕНИЕ

Parameter является элементом управления, назначением  которого является предоставление значений для заданного параметра. ASP.NET 2.0 поставляется с семью элементами управления Parameter - ControlParameter и более конкретными ControlParameter, CookieParameter, FormParameter, ProfileParameter, QueryStringParameter и SessionParameter - которые получают свои значения из элементов управления на странице, состояния сессии, полей строки запроса и т.д.

Если вам нужно использовать значение, которое не предоставлено ни одним из элементов управления Parameter, то вы можете использовать общий элемент управления Parameter и установить его значение программным путем. В качестве альтернативы, вы можете создать специализированный элемент управления Parameter, который получает конкретные необходимые данные. Создание такого специализированного элемента управления Parameter является несложной задачей. Читайте далее, чтобы узнать больше об этом!


Основы элемента управления Parameter

Класс Parameter в пространстве имен System.Web.UI.WebControls .NET Framework диктует основную функциональность каждого элемента управления Parameter. Элемент управления Parameter должен хотя бы предоставлять метод Evaluate() который возвращает значение для параметра. Данному метод Evaluate() передается два входных параметра:

  • Объект HttpContext, который представляет контекст HTTP-запроса, и включает в себя серверные объекты - Request, Session и т.д.
  • Ссылку на элемент управления, к которому привязан элемент управления Parameter (SqlDataSource или ObjectDataSource)
Метод Evaluate() просто возвращает значение параметра и как правило, код не содержит много строк. К примеру, встроенный QueryStringParamter, который возвращает значение конкретного поля строки запроса, имеет метод Evaluate(), который содержит всего три строки кода. Он гарантирует то, что переданный HttpContext объект не пуст (Null), и что его объект Request также не пуст (Null), и затем возвращает context.Request.QueryString(QueryStringField) (где QueryStringField является свойством QueryStringParamter, которое указывает название поля строки запроса, чье значение необходимо использовать).

При создании специализированного элемента управления Parameter нам также потребуется перегрузить метод Clone() класса Parameter. Метод Clone() создает детальную копию объекта параметра и его необходимо предоставить для того, чтобы довольствоваться поддержкой специализированных элементов управления Parameter во время проектирования.

И это все касательно элемента управления Parameter! В дополнение к созданию методов Evaluate() и Clone(), нам также может понадобиться добавление свойств элементов управления, которые влияют на значение, полученное из Evaluate(). (Также, как свойство QueryStringField элемента QueryStringParamter используется для указания названия поля строки запроса, чье значение должно быть возвращено.) Остальная часть данной статьи исследует два специализированных элемента управления Parameter, которые также могут быть загружены в конце данной статьи и сразу же использованы в ваших приложениях!



Создание элемента управления Parameter для получения текущего времени и даты

Бывают случаи когда нам нужно получить текущую дату и время и вставить их в конкретное значение времени\даты. К примеру, представьте, что у нас база данных Employees (сотрудники), где среди прочих колонок у нас будет колонка даты принятия на работу работника (HireDate). При добавлении нового работника посредством веб-сайта, нам наверняка захочется иметь значение текущей даты и времени в HireDate. Либо нам необходимо будет иметь элемент управления данными, который возвращает список всех сотрудников, нанятых за день. К сожалению, не существует встроенного элемента управления Parameter , который возвращал бы текущие дату и время, что означает, что нам надо установить данное значение программным путем.

Давайте исследуем способ создания нашего собственного элемента управления TodayParameter, который возвращает текущую дату (и в качестве опции - время). Код, который мы рассмотрим, написан на языке VB.

В приложении вы найдете решение в формате Visual Studio 2005, которое включает в себя два проекта: skmParameters, проект Visual Basic Control Library, и TestWebsite, который является веб-сайтом, основанным на файловой системе для тестирования skmParameters. Файл TodayParameter.vb в skmParameters включает в себя код для элемента управления TodayParameter. В простейшей форме мы сможем создать элемент управления TodayParameter таким образом, что он будет возвращать нам текущие дату и время:

Imports System.ComponentModel
Imports System.Web.UI.WebControls

Public Class TodayParameter
    Inherits Parameter

    Protected Overrides Function Evaluate(ByVal context As System.Web.HttpContext, ByVal control As System.Web.UI.Control) As Object
       Return DateTime.Now
    End Function
End Class

И это все! Конечно, без метода Clone() элемент управления TodayParameter должен быть изменен посредством декларативного синтаксиса, но все же это удовлетворяет минимальным требованиям. Для того, чтобы использовать данный параметр в ASP.NET-странице вам сначала понадобится добавть ссылку на проект (либо перетащить DLL из проекта в каталог сайта /bin), и затем "зарегистрировать" элемент управления (либо на уровне страницы, либо в Web.config). На уровне страницы это может быть выполнено используя директиву <% @Register %> следующим образом:

<%@ Register Assembly="skmParameters" Namespace="skmParameters" TagPrefix="skm" %> 

Далее, в одном из наборов параметров SqlDataSource либо ObjectDataSources вы можете использовать элемент управления TodayParameter. В приложении к данной статье вы найдете пример страницы (TodayParameter.aspx) , предоставляющей DetailsView , который позволяет добавление новых сотрудников в таблицу Employees. При добавлении нового сотрудника значение HireDate определяется при помощи элемента управления TodayParameter (что в результате дает текущую дату/время). Синтаксис для SqlDataSource будет следующим:

<asp:SqlDataSource ID="EmployeesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
   InsertCommand="INSERT INTO [Employees] ([Name], [Salary], [HireDate]) VALUES (@Name, @Salary, @HireDate)"
   SelectCommand="SELECT [EmployeeID], [Name], [Salary], [HireDate] FROM [Employees]">
   <InsertParameters>
      <asp:Parameter Name="Name" Type="String" />
      <asp:Parameter Name="Salary" Type="Decimal" />
      <skm:TodayParameter Name="HireDate" />
   </InsertParameters>
</asp:SqlDataSource>

Заметьте, что InsertCommand обладает параметром, названным @HireDate. Значение данного параметра указывается через TodayParameter из набора InsertParameters.

Мы можем далее расширить параметр TodayParameter путем предоставления свойства, которое указывает на то, что значение, которое необходимо вернуть, будет текущей датой либо временем:

Public Property IncludeTime() As Boolean
    Get
       Dim o As Object = ViewState("IncludeTime")
       If o Is Nothing Then
            Return True 'value not set, return default
       Else
            Return CType(o, Boolean)
       End If
    End Get
    Set(ByVal value As Boolean)
       ViewState("IncludeTime") = value
    End Set
End Property

Заметьте, что данное свойство сохраняет свое значение в наборе ViewState класса Parameter. Это обеспечит сохранение значения среди постбэков в случае, если значение данного свойства будет программно изменено.

Определив данное свойство мы можем обновить метод Evaluate() таким образом, чтобы оно теперь возвращало только текущую дату (без времени) в случае если IncludeTime равняется False:

Protected Overrides Function Evaluate(ByVal context As System.Web.HttpContext, ByVal control As System.Web.UI.Control) As Object
    If IncludeTime Then
       Return DateTime.Now
    Else
       Return DateTime.Now.Date
    End If End Function

Также можно изменить декларативную разметку элемента управления TodayParameter таким образом, чтобы она включала в себя данное значение (хотя на самом деле оно нужно только в случае, если вам необходимо передать время, поскольку значение по умолчанию IncludeTime равно True.

<skm:TodayParameter Name="HireDate" IncludeTime="False" />



Определение UserId авторизированного пользователя

Если вы используете Membership в ASP.NET 2.0 для управления информацией пользовательских записей, и если в вашей модели существует информация конкретного пользователя, то на каком-то этапе вам наверняка  захочется  добавить новую запись и использовать значение UserId авторизированного на данный момент пользователя,  или же отобразить информацию конкретного пользователя и получить данные авторизированного пользователя. Используя подсистему Membership, вы можете осуществить доступ к информации авторизированного пользователя при помощи Membership.GetUser(), и значение UserId будет возвращено в свойстве UserProviderKey класса MembershipUser. К сожалению, не существует встроенного элемента управления Parameter , который возвращал бы значение UserId на данный момент авторизированного пользователя. Это означает, что вам надо либо программно предоставить данное значение, либо... создать специализированный элемент управления Parameter! (Если вы не знакомы с подсистемой Membership в ASP.NET 2.0, то прочитайте серию статей "Исследуем Membership, роли и профили в ASP.NET 2.0" .)

Для облегчения задачи я создал элемент управления MembershipUserIdParameter , который возвращает UserId текущего пользователя. Код достаточно простой, и полностью зависит от интерфейса Membership API. Вот как выглядит метод Evaluate():

Protected Overrides Function Evaluate(ByVal context As System.Web.HttpContext, ByVal control As System.Web.UI.Control) As Object
    Dim currentUser As MembershipUser = Membership.GetUser()
    If currentUser Is Nothing Then
       'Either Membership is not setup or the visitor to this page is anonymous
       Return Nothing
    Else
       'Return the currently logged on user's UserId
       Return currentUser.ProviderUserKey
    End If
End Function

Вот и все! В приложении к данной статье вы найдете пример MembershipUserIdParameter.aspx, который имеет таблицу PersonalNotes в базе данных. Данная таблица базы данных разработана для того, чтобы пользователи могли  добавлять заметки. Каждая запись имеет UserId, что служит в качестве внешнего ключа обратно к колонке UserId в таблице aspnet_Users (одна из таблиц в схеме используемой провайдером SqlMembershipProvider).

Как демонстрирует следующая разметка, элемент управления MembershipUserIdParameter используется в наборе SelectParameters для возврата заметок авторизированного пользователя, а также в наборе InsertParameters для того, чтобы автоматически добавлять UserId авторизированного пользователя к выражению INSERT при добавлении новой заметки посредством DetailsView. Таблица PersonalNotes также имеет поле NoteDate для даты/времени; элемент управления TodayParameter используется для того, чтобы предоставить это значение в наборе InsertParameters.

<asp:SqlDataSource ID="PersonalNotesDataSource" runat="server"         ConnectionString="<%$ ConnectionStrings:ConnectionString         %>"    
    InsertCommand="INSERT INTO [PersonalNotes] ([UserId], [NoteDate], [Subject], [Body]) VALUES (@UserId, @NoteDate, @Subject, @Body)"
    SelectCommand="SELECT [PersonalNoteID], [UserId], [NoteDate], [Subject], [Body] FROM [PersonalNotes] WHERE UserId = @UserId ORDER BY NoteDate DESC"
>
    <InsertParameters>
       <skm:MembershipUserIdParameter Name="UserId" />
       <skm:TodayParameter Name="NoteDate" />

       <asp:Parameter Name="Subject" Type="String" />
       <asp:Parameter Name="Body" Type="String" />
    </InsertParameters>
    <SelectParameters>
       <skm:MembershipUserIdParameter Name="UserId" />
    </SelectParameters>
</asp:SqlDataSource>



Вывод

ASP.NET 2.0 поставляется с общим элементом управления Parameter и шестью особенными элементами управления, которые получают свое значение из конкретного источника. Написав небольшой код, вы можете создать свои собственные элементы управления Parameter. В данной статье мы увидели, как можно создать два специализированных элемента управления Parameter: TodayParameter, который возвращает текущую дату (а также, опционально,  время); и MembershipUserIdParameter, который возвращает UserId авторизированного пользователя (при использовании подсистемы Membership в ASP.NET). Данные специализированные элементы управления Parameter могут быть включены в набор параметров также, как и встроенные элементы управления Parameter. Изучите пример веб-сайта, приведенного в приложении к данной статье!

Scott Mitchell

Исходный код примеров