Accessing and Updating Data in ASP.NET: Creating Custom Parameter Controls
By Scott Mitchell
A Multipart Series on ASP.NET'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's data source controls.
Parameter controls for use in the data source controls' parameters collections.IDENTITY column value for the just-inserted record. |
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.)
A Parameter
controls is a control whose purpose is to provide a value for a given parameter. ASP.NET 2.0 ships with
seven Parameter
controls - the generic
ControlParameter
and
the more specific
ControlParameter
,
CookieParameter
,
FormParameter
,
ProfileParameter
,
QueryStringParameter
,
and SessionParameter
controls -
which pull their values from web controls on the page, session state, querystring fields, and so on.
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 custom Parameter
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)
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:
Imports System.ComponentModel
|
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:
<%@ Register Assembly="skmParameters" Namespace="skmParameters" TagPrefix="skm" %>
|
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:
<asp:SqlDataSource ID="EmployeesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
|
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
|
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
|
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.
<skm:TodayParameter Name="HireDate" IncludeTime="False" />
|
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
|
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.
<asp:SqlDataSource ID="PersonalNotesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
|
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!
Happy Programming!
Further Readings:
Attachments
A Multipart Series on ASP.NET'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's data source controls.
Parameter controls for use in the data source controls' parameters collections.IDENTITY column value for the just-inserted record. |