Accessing and Updating Data in ASP.NET 2.0: Creating Custom Parameter Controls
By Scott Mitchell
A Multipart Series on ASP.NET 2.0's Data Source Controls
ASP.NET 2.0 introduced a number of new Web controls designed for accessing and modifying data.
These controls allow page developers to declaratively access and modify data without writing any
code to perform the data access. This article is one in a series of articles on ASP.NET 2.0's new data
source controls.
Data Source Control Basics - explores the concepts
and advantages of data source controls, and compares their usage in ASP.NET 2.0 to data access techniques in ASP.NET 1.x.
Accessing Database Data - shows how to use the
SqlDataSource and AccessDataSource controls to query data from a relational database.
Filtering Database Data with Parameters - learn how to
retrieve just a subset of database data based on hard-coded values and values from the querystring, other Web controls on the page,
session variables, and so on.
Creating Custom Parameter Controls - learn how
to create your own custom, declarative Parameter controls for use in the data source controls' parameters collections.
Inserting Data - learn how to insert data using
a SqlDataSource control. Also examines how to retrieve the IDENTITY column value for the just-inserted record.
Deleting Data - see how to delete data using
a SqlDataSource control. Also looks at how to programmatically cancel a delete.
Updating Basics - learn the basics of updating database data using a
SqlDataSource control. Also examines using the GridView to provide a web-based editing interface.
Customizing the Editing Interface - see how to
customize the GridView's columns to provide a customized editing interface that includes input validation and alternative
user interface elements.
Handling Database NULL Valuese - explore how to
extend the GridView's customized editing interface to handle database NULL values.
Introduction
As discussed in previous installments of this article series, ASP.NET 2.0
ships with a number of built-in data source controls
that can be used to programmatically access data (the SqlDataSource, ObjectDataSource, XmlDataSource,
and so on). The SqlDataSource and ObjectDataSource commonly return or modify data based upon parameters. For example,
a SqlDataSource might use a parameterized query, like SELECT * FROM TableName WHERE ColumName = @parameterName;
the ObjectDataSource's parameters are those expected input parameters to the methods it invokes.
In either case, the values of the parameters can be specified using Parameter controls.
(See Filtering Database Data with Parameters installment
for more information on using parameters with the data source controls.)
If you need to use a value that's not provided by one of the specific Parameter controls, you can use
the generic Parameter control and set its value programmatically (a topic we'll address in a future article
in this series). Alternatively, you can create a customParameter control that grabs the specific data
you need. Creating such a custom Parameter control is quite easy and straightforward, as we'll see in this
article. Read on to learn more!
Parameter Control Basics
The Parameter class in the .NET Framework's System.Web.UI.WebControls namespace spells out the core
functionality of every Parameter control. At a minimum, a Parameter control must provide an
Evaluate() method
that returns the value for the parameter. This Evaluate() method is passed two input parameters:
An HttpContext object that represents the context of the HTTP request, and includes the intrinsic server objects -
Request, Session, and so on, and
A reference to the control that the Parameter control is bound to (the SqlDataSource or ObjectDataSource)
The Evaluate() method simply returns the value for the parameter and, as such, the code for this method is
typically very short and simple. For example, the built-in QueryStringParamter, which returns the value of a specified
querystring field, has an Evaluate() method that's a scant three lines of code. It checks to ensure that
the passed-in HttpContext object is not null, and that its Request object is not null, and then
returns context.Request.QueryString(QueryStringField) (where QueryStringField is the QueryStringParamter
property that specifies the name of the querystring field whose value to use).
When creating a custom Parameter control, we'll also want to override the Parameter class's
Clone() method.
The Clone() method creates a deep copy of the parameter object and needs to be provided in order to enjoy
design-time support for custom Parameter controls; see Eilon Lipton's
blog entry, Custom Parameters for Data Sources for
more information on the need for supplying the Clone() method to obtain design-time support.
That's all there is to a Parameter control! In addition to creating the Evaluate() and Clone() methods,
we might also want to add control properties that affect the value returned from Evaluate(). (Like how the
QueryStringParamter's QueryStringField property is used to indicate the querystring field name
whose value is to be returned.) The remainder of this article examines two custom Parameter controls I created,
which can be downloaded at the end of this article and immediately used in your ASP.NET 2.0 applications!
Creating a Parameter Control to Return the Current Date and Time
In certain scenarios we want to have the current date and time inserted into a particular date/time value. For example,
imagine that we had an Employees database table that, among other columns, had a HireDate column.
When adding a new employee through the website, we might want to have the HireDate value be today's date and time.
Or we may want to have a data source control that returns all employees hired today. Unfortunately, there's no built-in
Parameter control that returns the current date and time, meaning we have to have this parameter value set
programmatically.
Let's examine how to create our own TodayParameter control that returns the current date (and, optionally,
the time). This parameter was inspired by Eilon Lipton's
Custom Parameters for Data Sources blog entry. The code
we'll be examining is in VB; Eilon's blog entry provides similar functionality, but is written in C#.
In the download you'll find a Visual Studio 2005 Solution that includes two projects: skmParameters, a Visual Basic Control
Library project, and TestWebsite, which is a file system-based website for testing skmParameters. The TodayParameter.vb
file in skmParameters includes the code for the TodayParameter control. In the simplest form, we could create
the TodayParameter control so that it blindly returns the current date and time:
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
That's all there is to it! Of course without the Clone() method, the TodayParameter control will
need to be modified through the declarative syntax (as there will be no design-time support), but it meets the minimum requirements.
To use this parameter in an ASP.NET page, you'd first need to add a reference to the project (or drop the DLL from the project
into the website's /bin folder), and then "register" the control (either at the page level or in Web.config).
At the page level, this can be accomplished by using the <% @Register %> directive like so:
Then, in one of the SqlDataSource or ObjectDataSources parameters collections, the TodayParameter control can
be used. In the download at the end of this article you'll find a demo page (TodayParameter.aspx) that provides
a DetailsView that allows new employees to be added to the Employees table. When adding a new employee, the
HireDate value is determined via the TodayParameter control (resulting in the current date/time).
The syntax for the SqlDataSource is as follows:
Notice how the InsertCommand has a parameter named @HireDate. This parameter value is specified
via the TodayParameter in the InsertParameters collection.
We can further augment the TodayParameter by providing a property that specifies whether the value returned
should be just the current date or the current date and time:
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
Note that this property persists its value to the Parameter class's ViewState collection. This
ensures that the if the value for this property is changed programmatically, that the changed value is
persisted across postbacks. For a more in-depth look at view state, it's purpose, and why custom controls are responsible
for managing their own view state (and common design patterns in doing so), see my article
Understanding ASP.NET View State.
With this property defined, we can update the Evaluate() method so that it returns only the current date (and not the
time) if IncludeTime is 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
And the TodayParameter control's declarative markup can be modified to include this value (although it's really
only needed if you want to omit the time, since the default value of IncludeTime is True.
Determining the Currently Logged On User's UserId
If you use ASP.NET 2.0's new Membership feature to manage user account information, and if there is user-specific data in
your data model, you've no doubt come across a situation where you want to add a new record and use the currently logged in
user's UserId value. Or maybe you are listing information specific to a user and want to get the data for the currently
logged in user. When using the Membership system, the currently logged on user's information can be accessed using
Membership.GetUser(), and the UserId value is returned in the MembershipUser object's
UserProviderKey property. Unfortunately, there is no built-in Parameter control that returns
the currently logged in user's UserId value, meaning we either have to programmatically provide this value, or...
create a custom Parameter control! (If you are not familiar with ASP.NET 2.0's Membership subsystem,
check out the Examining ASP.NET 2.0's Membership, Roles, and
Profile article series.)
To facilitate this, I've created a MembershipUserIdParameter control that returns the currently logged on user's
UserId. Needless to say, the code is very simple, relying entirely on the Membership API. The Evaluate() method
follows:
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
That's all there is to it! In the download at the end of this article, you'll find a MembershipUserIdParameter.aspx
demo that has a PersonalNotes table in the database. This database table is designed to allow logged on user's
to add personal reminders or TODO notes. Each record has a UserId record, which serves as a foreign key back
to the UserId column in the aspnet_Users table (one of the tables in the schema used by the
SqlMembershipProvider provider).
As the following markup shows, the MembershipUserIdParameter control is used in the
SelectParameters collection to return the notes for the currently logged on user, and in the InsertParameters
collection to automatically add the currently logged on user's UserId to the INSERT statement when adding a new
note through a DetailsView. The PersonalNotes table also has a NoteDate date/time field; the
TodayParameter control is used to provide that value in the InsertParameters collection.
Conclusion
ASP.NET 2.0 ships with a generic Parameter control and six specific controls, who pull their value from a
particular source. With just a little bit of code, you can create your own custom Parameter controls. In this article
we saw how to build two custom Parameter controls: TodayParameter, which returned the current date
(and, optionally, the time); and MembershipUserIdParameter, which returned the currently logged on user's
UserId (when using ASP.NET's Membership subsystem). These custom Parameter controls can be included in the
parameter collections just like the built-in Parameter controls. Be sure to check out the test website and code
available for download at the end of this article!
A Multipart Series on ASP.NET 2.0's Data Source Controls
ASP.NET 2.0 introduced a number of new Web controls designed for accessing and modifying data.
These controls allow page developers to declaratively access and modify data without writing any
code to perform the data access. This article is one in a series of articles on ASP.NET 2.0's new data
source controls.
Data Source Control Basics - explores the concepts
and advantages of data source controls, and compares their usage in ASP.NET 2.0 to data access techniques in ASP.NET 1.x.
Accessing Database Data - shows how to use the
SqlDataSource and AccessDataSource controls to query data from a relational database.
Filtering Database Data with Parameters - learn how to
retrieve just a subset of database data based on hard-coded values and values from the querystring, other Web controls on the page,
session variables, and so on.
Creating Custom Parameter Controls - learn how
to create your own custom, declarative Parameter controls for use in the data source controls' parameters collections.
Inserting Data - learn how to insert data using
a SqlDataSource control. Also examines how to retrieve the IDENTITY column value for the just-inserted record.
Deleting Data - see how to delete data using
a SqlDataSource control. Also looks at how to programmatically cancel a delete.
Updating Basics - learn the basics of updating database data using a
SqlDataSource control. Also examines using the GridView to provide a web-based editing interface.
Customizing the Editing Interface - see how to
customize the GridView's columns to provide a customized editing interface that includes input validation and alternative
user interface elements.
Handling Database NULL Valuese - explore how to
extend the GridView's customized editing interface to handle database NULL values.