Using Expression Builders in ASP.NETBy Scott Mitchell
ASP.NET offers a variety of ways to inject the results of a server-side expression (such as
DateTime.Now.ToString()) into the rendered markup of an ASP.NET page. The most common way is to add a Label Web control to the page and then from the
Page_Loadevent handler (or some other suitable event handler) assign the value to display to the Label's
Textproperty. If you ever created web applications using ASP.NET's predecessor, classic ASP, or if you are familiar with Microsoft's ASP.NET MVC, then you know that another way to inject server-side information is to add
<%= expression %>to the declarative content like so:
<%= expression %> syntax is translated into
Response.Write(expression), injecting the value of expression into the
page's rendered output. Because
<%= expression %> is translated into (essentially) a
Response.Write these statements cannot be used to set the values
of Web control properties. In other words, you cannot have markup like the following:
An alternate way to display server-side information is to assign it to a Web control property directly from the declarative markup using an expression builder. An
expression builder is denoted using the syntax
<%$ expression %> (note the
The expression cannot be an arbitrary snippet of code as with
<%= ... %>, but instead is limited to what expression builders the website is configured
to use. Moreover, expression builders must be assigned to a Web control property; they cannot appear in any which place in the declarative markup like
<%= expression %>.
ASP.NET ships with three built-in expression builder classes that let you declaratively access the values in the configuration's
AppSettings collection, the
ConnectionStrings collection, and in the website's resources (typically defined in the
With a little bit of code you can create your own expression builders. This article provides an overview of how expression builders work and shows how to create your
own expression builders. Read on to learn more!
A Primer on How Declarative Markup Is Translated Into Code
When an ASP.NET page is visited the declarative markup in the page is converted into source code and compiled into an assembly that derives from the page's code-behind class. In short, this step turns the declarative markup - the static HTML content and Web control markup - into a C# or Visual Basic class file. This auto-generated class's primary responsibility is to create the page's control hierarchy, which involves creating
LiteralControls for each block of static HTML, creating objects that represent each Web control on the page, and adding these controls to the
Controlscollection. You can find these auto-generated classes in the
%WINDOWS%\Microsoft.NET\Framework\version\Temporary ASP.NET Filesfolder.
Consider the following simple page, which has a Web Form (
<form runat="server">), inside which there is a mix of static HTML and Web controls, namely
a TextBox, Button, and Label.
When this page is visited for the first time (or for the first time after the page's content has changed) the declarative markup is transformed into a class file that constructs
the page's control hierarchy based on the contents in the declarative markup. The control hierarchy construction is kick started by the auto-generated class's
FrameworkInitialize method, which contains a call to a method named
@__BuildControlTree is where the magic happens.
@__BuildControlTree starts by creating a
LiteralControl that contains the static HTML markup at the start of the document (
<body>, etc.). Next, it generates the control hierarchy for the Web Form. It completes by creating a
that contains the static HTML markup at the end of the document (
@__BuildControlform1 method creates the control hierarchy for the Web Form, creating and adding Web control objects for each Web control defined in the Web
Form. This method also sets the properties for the Web Form that are defined in the declarative markup (the
ID, for instance).
The methods that create the corresponding Web control objects follow a similar pattern: they create the Web control in question and set those properties that were defined
in the declarative markup. If the Web control has children controls, the logic recurses into additional method calls to add those children Web controls. Here's the
code for the
@__BuildControlbtnSubmit, which generates the object and sets the properties for the Button Web control.
As you can see, those Button properties defined explicitly in the markup -
Text - are assigned to "btnSubmit" and "Click Me!", respectively.
As I noted in the introduction, one way to inject server-side information into the rendered markup is to use
<%= expression %>. Adding such
content writes expression directly to the output stream alongside the other literal content on the page. That is why you cannot assign a Web control value using the
<%= expression %> syntax.
Enter Expression Builders
Starting with ASP.NET 2.0 it is possible to have more control over the value assigned to the Web controls' properties by the auto-generated class. Instead of only being able to assign a static value to a property via the declarative syntax (as in
<asp:Label ... Text="Hello!" />), it is possible to use an expression builder to assign the property a dynamic value. With an expression builder you use the syntax
<%$ expression %>to assign a Web control property a dynamic value (as in
<asp:Label ... Text="<%$ expression %>" />).
When the runtime converts the declarative markup to the auto-generated class file, it parses the expression builder syntax to determine what expression builder class is responsible
for generating the corresponding expression. Such a class must extend the
class, which spells out the default functionality for expression builders. Specifically, the corresponding expression builder class's
method is called and passed information about the Web control property the expression builder is being bound to, the value of expression in the
<%$ expression %> syntax, and other information. The expression builder class is responsible for generating a
CodeExpression instance that will be used to assign the Web control's
property value. (The
CodeExpression class is part of the .NET Framework's CodeDom library, which allows for developers to write code that generates code.)
To better understand how expression builders work, let's review the
class, which is one of three expression builder classes that are built into the .NET Framework. As its name implies, the
is used to return values from the
AppSettings section defined in the application's configuration (
Web.config). For example, imagine that you have
Web.config file with the following
You could use an expression builder like so to display this value in a Label control on an ASP.NET page:
When this page was first visited and the declarative markup converted into an auto-generated class that constructs the control hierarchy, the runtime would parse the
<%$ AppSettings:CopyrightNotice %> and say, "Ah, I need to call the
method in order to correctly assign the property value to this Label's
Text property." The
GetCodeExpression method would then be invoked.
AppSettingsExpressionBuilder class would see that the request was for the AppSettings key "CopyrightNotice". It would then return a
instance that specified the code to execute as
AppSettingsExpressionBuilder.GetAppSettings("CopyrightNotice", typeof(Label), "Text"). This code is actually injected
into the auto-generated class in the method that creates the Label and sets it properties.
Consider the code that is auto-generated if the Label's
Text property is assigned a static value, such as "Hello, World!" As we discussed earlier, it would look something like:
This is as we expect. But notice the code that gets generated when using an expression builder (namely
<%$ AppSettings:CopyrightNotice %>):
Look at that! The actual code specified via the
CodeExpression object in the
AppSettingsExpressionBuilder class is echoed into the code for the
auto-generated class. The
AppSettingsExpressionBuilder.GetAppSettings method, as you may have guessed, gets and returns the specified AppSettings value via the
ConfigurationManager.AppSettings collection. The net result is that a developer can inject server-side information into the property of a Web control in the
declarative portion by using an expression builder. When the declarative markup is translated into code, the expression builder gets to inject code into this auto-generated
class, such as pulling a value from the AppSettings, returning the current date and time, or any other number of tasks.
Creating a Custom Expression Builder Class
The .NET Framework ships with three built-in expression builder classes:
AppSettingsExpressionBuilder- retrieves a value from the AppSettings defined in the web application's configuration file.
ConnectionStringsExpressionBuilder- retrieves a value from the ConnectionStrings defined in the web application's configuration file.
ResourceExpressionBuilder- retrieves a resource value. Resources are commonly used to specify culture-specific values for localized applications.
ExpressionBuilderclass, which defines the base functionality. Moreover, your class must implement, at minimum, the
GetCodeExpressionclass, whose duty it is to return a
CodeExpressionobject that contains the code to inject when assigning the code expression to a Web control property in the auto-generated class.
Let's create a custom expression builder class named
SessionExpressionBuilder that allows page developers to declaratively assign Session variables to properties
of Web controls in the declarative markup. The idea here is that a page developer could display the value of a Session variable named, say, "Foo", in a Label control using the
following declarative markup:
To start, we need to create a class that extends
ExpressionBuilder (which is found in the
System.Web.Compilation namespace). Moreover, we need to override the
The GetCodeExpression method needs to return a
CodeExpression object, which can be one of any number of code generation tasks. For instance, the
CodeExpression could perform a binary operation (such as addition), generate primitive expression (such as a literal string or number), or invoke a method,
among other options. We want the
CodeExpression to invoke a method so that the auto-generated class calls a method in our custom expression builder class when
assigning the expression builder value to the Web control property. For this reason, the
GetCodeExpression returns a
object that calls
GetRequestedValue, a static method in the custom expression builder class:
CodeMethodInvokeExpression constructor accepts:
- The type that the method being called belongs to (
this.GetType(), which returns the type of the custom expression builder class,
- The method name to invoke ("GetRequestedValue"), and
- The input parameters to pass into this method. We are passing in three parameters: the expression in the
<%$ expression %>syntax, which is accessible via the
Expressionproperty of the
BoundPropertyEntryobject passed into the
GetCodeExpressionmethod; the type of the Web control whose property is being assigned; and the name of the property being assigned.
GetRequestedValuemethod, shown below, checks to ensure that the Session variable of interest exists. Next, it compares the type of the property being assigned and the type of the Session variable being assigned to it. If there is a type mismatch it ensures that the Session variable type can be converted to the Web control property type and then performs the conversion. If the two types match, it simply returns the Session variable value.
Before you can use the custom expression builder in your project you need to register it in
Web.config. Go to the
<compilation> element and
add the following:
Replace prefix with the expression builder prefix you want to use, such as "Session". Replace type with the type name of the custom expression builder class.
If you added it to the
App_Code folder in a Web Site Project the type is simply the name of the class,
SessionExpressionBuilder. If you are
using a Web Application Project or have the expression builder class in a separate Class Library project, the type should include the namespace and assembly, like so:
With this configuration information in place you can now use the expression builder in an ASP.NET page. For example, imagine that you had a page with a Label and you wanted to set the Label's Text and Font-Size properties based on Session variables "Message" and "MessageFontSize", respectively. You could use declarative markup like the following to achieve this:
When this page is visited and the declarative markup is translated into an auto-generated class, the class assigns the Label's
properties a value returned by the
SessionExpressionBuilder.GetRequestedValue method. The code that gets auto-generated looks like the following:
SessionExpressionBuilder.GetRequestedValue method is grabbing the passed-in Session variable ("Message" and "MessageFontSize") from Session state and
returning its value, which is then assigned to the Label's
Assuming that you have specified the values for these two Session variables previously in the user's session, the Label will incorporate these Session variables' values. The screen shot below shows a demo that's available for download at the end of this article. Prior to visiting this page the following code was executed:
The result is that the Label's
Text property is set to "Welcome to My Website (FROM SESSION!)" and its
Font-Size property set to 48pt.
One Custom Expression Builder Library To Rule Them All!
It would have been nice if the .NET Framework had shipped with more expression builders. To address that shortcoming, I've decided to create my own library of custom expression builder classes that you are welcome to download and use in your projects. This library, named skmExtensionBuilders, is available for download at the end of this article, along with a demo website that shows these expression builders in action. (And, if you couldn't guess, it includes the
SessionExpressionBuilderwe just examined.) To learn more about this library check out: skmExpressionBuilders - A Suite of Custom Expression Builder Classes.
Until then... Happy Programming!
ExpressionBuilderClass Technical Docs