Dynamic Content Substitution usi

Dynamic Cache Substitution using Substitution Control


ASP.NET Output Caching features help us to develop performance oriented web sites. No doubt that output caching reduces server side event processing. However, in the process it bypasses the entire server side processing. That means after the first request the page becomes static in terms of its contents for the entire cache duration. In some situations this architecture poses problems of its own. Recognizing these problems Microsoft introduced a new web server control called Substitution control in ASP.NET 2.0. The Substitution control allows you to dynamically change a part of the entire cached output. This substitution happens on the server and you can control what to substitute in the output.

Sample Scenario

In order to understand the problem behind normal output caching behavior we will develop a simple application.

Create a new web site using VS.NET. Add two web forms - Article.aspx and Login.aspx. Design Artile.aspx as shown below:

The application is protected using Forms authentication. At the top there is a welcome message displayed for the logged in user. Below there is a LinkButton for signing out. Finally the article content is displayed. The article content is stored in an XML file (in real world cases it will come from database).

Similarly design Login.aspx as shown below:

The Login.aspx simply contains a TextBox for entering user name. For the sake of simplicity we have skipped the user authentication logic.

Enabling forms authentication

Now, open web.config file and add the following markup to it.

<authentication mode="Forms"/>
   <deny users="?"/>

Here, we set the authentication mode to Forms. Note that default URL for login page is Login.aspx and hence we need not configure it separately. We also blocked anonymous uses using <authorization> tag.

Now open Login.aspx and add the following code in the Click event handler of Submit button.

protected void Button1_Click(object sender, EventArgs e)
FormsAuthentication.SetAuthCookie(TextBox1.Text, false);

We call SetAuthCookie() method of FormsAuthentication class. The SetAuthCookie() method issues an authentication cookie to the user. In read world scenarios you will execute some database driven logic before issuing the authentication cookie. The first parameter of SetAuthCookie() method represents the user name. The second parameter indicates whether to persist the authentication cookie even if browser windows is closed or not. After issuing the authentication cookie the user is redirected to the Article.aspx page.

Note: Discussing forms authentication is out of the scope of this article. If you wish to learn forms authentication in detail refer the following articles.

Forms Authentication in ASP.NET
Applying Forms Authentication Selectively
Forms Authentication Against An XML File
Membership, Roles and Profile - An Example (Part 1)
Membership, Roles and Profile - An Example (Part 2)

Creating an XML file to store article contrnt

Add an XML file to your web site and key in the following markup:

<?xml version="1.0" encoding="utf-8" ?>
    <title>.NET The Great</title>
      <![CDATA[article body goes here]]>

Save the file as Article.xml. The Article.xml file supplies the content of the article. The tag names used are self explanatory and need no elaboration.

Displaying the article

Open Article.aspx in the IDE and design it as shown above. Write the following code in the Page_Load event handler.

protected void Page_Load(object sender, EventArgs e)
Label2.Text = User.Identity.Name + " !";
DataSet ds = new DataSet();
Label5.Text="By " + ds.Tables[0].Rows[0]["author"].ToString();

The code assigns the user name of the currently logged in user to a label. This is done with the help of User.Identity.Name property. This way the end user sees the welcome message in the browser. It then creates a DataSet and reads Article.xml file into it using ReadXml() method. The ReadXml() file accepts the path of the XML file to read and generates DataTable(s) in the DataSet. Because of the nesting of our file it will create only one DataTable with three columns - title, author and content. The column values are retrieved from the DataSet and assigned to the respective labels.

In the Click event handler of Sign Out button add the following code:

protected void LinkButton1_Click(object sender, EventArgs e)

The code simply calls the SignOut() method of FormsAuthentication class. This method removes the authentication cookie that we issued initially. The user is then taken to the login page.

Finally, enable caching for Article.aspx by adding @OutputCache directive as shown below:

<%@ OutputCache Duration=60 VaryByParam=None %>

The @OutputCache directive sets the duration of caching to 60 seconds.

Now we are ready to see the problem!

Testing the application and knowing the problem

Run the Login.aspx. Enter some user name (say User1) and click on submit button. You will be taken to the Article.aspx page and a welcome message will be displayed (say Welcome User1). Now click on Sign Out button so that you will be signed out and taken to login page again. Enter another user name (say User2) and click on submit button. You will be taken to the Article.aspx but this time welcome message doesn't change. It still shows the previous user name. That's the problem! Since @OutputCache directive caches the entire page output even the user name is cached. This is certainly not what we want. Thankfully the Substitution control helps to resolve the problem.

Substitution control to the rescue

Let's modify Article.aspx to use Substitution control. Drag and drop a Substitution control from toolbox below the welcome label.

Go in the code behind and create a static method called GetUserName. The method is shown below:

public static String GetUserName(HttpContext context)
return "<h3>Welcome " + context.User.Identity.Name + " !</h3>";

This method is responsible for generating the content that is to be substituted dynamically. The method signature must match following rules:

  • It must be defined as a static method 
  • It must accept a parameter of type HttpContext
  • The return type must be string

Inside the method you can not access any controls or class level instance variables but you can access objects such as Request, Response and User via the HttpContext parameter. In our example the GetUserName method returns the user name of currently logged in user i.e the content that we want to change dynamically.

This method is linked with the Substitution control via a property called MethodName. The MethodName property of Substitution control specifies the name of the method that will be invoked when the request is made to the page. The method of course must follow the above rules.

Run the Article.aspx page again and test it as before. You will find that the welcome label continues to show User1 but the Substitution control correctly displays the newly entered user name. The following Figure shows a sample run of Article.aspx with Substitution control.

Thus the Substitution control helps us to dynamically change part of the total cached page. Though we have seen the use of Substitution control for a web form the same concept is applicable for Web User Controls also.


Bipin Joshi is an independent software consultant and trainer by profession specializing in Microsoft web development technologies. Having embraced the Yoga way of life he is also a yoga mentor, meditation teacher, and spiritual guide to his students. He is a prolific author and writes regularly about software development and yoga on his websites. He is programming, meditating, writing, and teaching for over 27 years. To know more about his private online courses on ASP.NET and meditation go here and here.

Posted On : 01 September 2006

Tags : ASP.NET Web Forms Server Controls Performance