skmExpressionBuilders - A Suite of Custom Expression Builder Classes
By Scott Mitchell
Introduction
An ASP.NET Web control's properties can be set in one of two ways: declaratively and programmatically. Declaratively setting a Web control's properties entails specifying
the property in the control's declarative syntax. For example, Web controls have their ID property set declaratively, like so:
<asp:WebControl runat="server" ID="ID" ... />. Properties can also be set programmatically in the ASP.NET
page's code-behind class. If you need to set a Web control's property to some dynamic value you may think you need to set it programmatically. However, this is not the case.
Expression builders make it possible to assign a dynamic value to a Web control property through the declarative syntax.
Last week's article, Using Expression Builders in ASP.NET, examined the ins and outs of expression
builders, their syntax, and how to use them in an ASP.NET page. ASP.NET ships with three built-in expression builder classes: AppSettingsExpressionBuilder,
which retrieves a value from the <appSettings> section defined in Web.config; ConnectionStringsExpressionBuilder, which retrieves a
value from the <connectionStrings> section; and ResourceExpressionBuilder, which retrieves a resource value. These expression builders can be
used in the declarative markup using syntax similar to the following: <asp:Label runat="server" id="Copyright" Text="<%$ AppSettings:CopyrightNotice
%>" />.
With a little bit of elbow grease you can create your own custom expression builder classes. I've spent some time creating a handful of custom expression builder classes,
which I've packaged into a class library named skmExpressionBuilders. This article walks through the custom expression builders in this library and shows how to use them in
your ASP.NET application. Read on to learn more!
An Overview of the skmExpressionBuilders Library
The download available at the end of this article includes a Visual Studio Solution with two projects: a website application for testing the custom expression builders
(TestWebsite), and a Class Library project named skmExpressionBuilders. skmExpressionBuilders includes four custom expression builder classes:
SessionExpressionBuilder - retrieves a specified Session variable value using the syntax <%$ Session:VariableName %>.
QueryStringExpressionBuilder - retrieves a specified querystring value using the syntax <%$ QueryString:Name %>.
ServerVariableExpressionBuilder - retrieves a specified value from the ServerVariables
collection. This collection contains information about the current request, such as the requested URL, whether the request is over HTTPS, the currently logged on
user's name, the IP address of the requestor, and HTTP headers, among other information. This custom expression builder uses the syntax <%$ ServerVariable:VariableName %>.
CodeExpressionBuilder - returns the value of a specified expression using the syntax <%$ Code:CodeExpression %>.
We'll dissect these expression builders in a moment, but before we do let's first talk about the steps you'll need to take to use the skmExpressionBuilders
library in your web application. skmExpressionBuilders will work with ASP.NET 2.0 and beyond, and while the skmExpressionBuilders is written in C#, it can be used in any
ASP.NET web application regardless of the language used.
To use skmExpressionBuilders in your website follow these two simple steps:
Copy the skmExpressionBuilders.dll assembly from the download available at the end of this article into the /Bin folder of your ASP.NET application.
Open your website's Web.config file and add the following markup within the <compilation> section in <system.web>:
That's all there is to it! You can now add these handy expression builders in your declarative syntax.
The SessionExpressionBuilder, QueryStringExpressionBuilder, and ServerVariableExpressionBuilder Custom Expression Builders
The first three custom expression builders in the skmExpressionBuilders library - SessionExpressionBuilder, QueryStringExpressionBuilder,
and ServerVariableExpressionBuilder - are all very similar. Each of these custom expression builders pulls a value from a collection in a server-side object.
SessionExpressionBuilder retrieves a Session variable, whereas QueryStringExpressionBuilder pulls a value from the querystring.
Because these three classes are so similar I created a base class, BaseServerObjectExpressionBuilder, which extends the ExpressionBuilder class and
implements the common functionality. The classes that derive from BaseServerObjectExpressionBuilder only need to do three things:
Provide a static method named Instance that returns a new instance of the class.
Override the GetValue method defined in the BaseServerObjectExpressionBuilder class. The GetValue method accepts a string input
and returns an object. Specifically, GetValue should return the value in the server-side collection of interest.
Override the SourceObjectName property, which supplies the name of the collection being worked with; it is used in any error message strings.
Take the QueryStringExpressionBuilder class as an example. As you can see, this class is quite simple as it only needs to do the three things noted above. The
code that generates the code expression based on the user's input and casts it to the appropriate type (if needed) is handled in the BaseServerObjectExpressionBuilder
base class.
public class QueryStringExpressionBuilder : BaseServerObjectExpressionBuilder
{
public static QueryStringExpressionBuilder Instance()
{
return new QueryStringExpressionBuilder();
}
public override string SourceObjectName
{
get { return "QueryString"; }
}
}
If you'd like to create any additional custom expression builders that perform a similar function to these three - namely, a custom expression builder that grabs some value
from a server-side object like Session or Request.QueryString - have your class extend BaseServerObjectExpressionBuilder and implement
the aforementioned requisites.
Let's look at using these three expression builders. Imagine you had a search page that was passed the search criteria through the a querystring field named query,
as in: /SearchResults.aspx?query=user's search query. Furthermore, assume that the search results had a TextBox at the top from which the user could
start a new search. You could populate this TextBox with the user's current search query by assigning the TextBox's Text property declaratively with the
following expression builder syntax:
The download includes a test website with additional demos.
CodeExpressionBuilder, A Generic Code Expression Builder
In his blog entry The CodeExpressionBuilder, Microsoft ASP.NET team member
Dave Reed showcased a very generic and powerful custom expression builder that can evaluate any
ad-hoc code expression, assigning the result to a Web control property. I added this control into skmExpressionBuilders (with permission).
With the CodeExpressionBuilder you can assign any generic code expression statement to a property value. You could, for instance, display the current date
and time in a Label using the following syntax:
A code expression is some statement that evaluates to a value, like:
DateTime.Now.ToString()
4 + 17
"Your IP address is: " + Request.ServerVariables["REMOTE_ADDR"]
The code expression you specify for the CodeExpressionBuilder must be in the same language as specified in the Language attribute of the ASP.NET
page's @Page directive. Also, if your code snippet includes quotation marks you'll need to make sure you surround the property value in the declarative syntax
with apostrophes so that there's no ambiguity where the strings start and end. For example, when assigning the Text property of a Label to the code expression "Your IP address is: " +
Request.ServerVariables["REMOTE_ADDR"] you should surround the value of the Text property with apostrophes, like so:
<asp:Label runat="server" id="UsersIP" Text='<%$ Code:"Your IP address is: " + Request.ServerVariables["REMOTE_ADDR"] %>' />
You can also perform simple if/then/else-type operations using the ternary operator. The C# ternary operator takes the form:
Boolean Expression ? Output If True : Output If False
So you could use this expression builder to assign a different value to a Label depending on whether the user was authenticated or not like so:
Moreover, you can always call a method defined in your page's code behind class. We could replicate the above functionality by created a protected or public method in the
code-behind class named GenerateWelcomeMessage. This method would need to return a value that will be assigned to the property in question; in this case, we'd want
the GenerateWelcomeMessage method to return a string.
Design-Time Support
The expression builder syntax can be specified directly in the declarative syntax, as my examples in this article and last
week's article have demonstrated, but you can also use a GUI for supplying these values. Go to the Designer in Visual Studio, click on a Web control, and go to the Properties
window. At the top of the Properties window is the text (Expressions). Click the ellipses next to this option to display the Expressions dialog box.
From this dialog box you can select a bindable property, choose the expression type from a drop-down list, and then enter the expression property. The following screen shot
shows the Expressions dialog box for a TextBox whose Text property is assigned using the SessionExpressionBuilder custom expression builder, pulling in
the value of the DefaultName Session variable.
The skmExpressionBuilders custom expression builders each include support in this dialog box. Moreover, the GUI for the ServerVariableExpressionBuilder
is comprised of a drop-down list with the server variable options pre-loaded. (You can manually type in a value into the drop-down list, as well.)