Managing Cached Content

9/20/2010 5:53:38 PM
In some cases, it's enough to blindly cache the content of certain pages by simply putting the OutputCache directive in the page. However, sometimes you need a bit more control over what's happening in the output cache. ASP.NET supports a number of parameters you can use to manage the way the cache functions. You can control the output caching behavior by either changing the parameters in the OutputCache directive or tweaking the HttpCachePolicy property available through the Response object.

1. Modifying the OutputCache Directive

It's often very useful to be able to govern output caching. For example, some pages present exactly the same content to all the users who access the page. In that case, caching a single version of the content is just fine. However, there are other circumstances in which sending the same content to everyone is inappropriate. The easiest way to control the behavior of output caching is to modify the OutputCache directive.

One obvious case in which controlling the cache is important is while caching different versions of content for different browsers making requests. Different browsers often have different capabilities. If you send content that requires a feature not supported by all browsers, some browsers making requests will get a response that they're unable to handle adequately. With the VaryByCustom parameter in the OutputCache directive, you can cache different content based on different browsers.

Controlling the output caching is also important when your page renders content based on the parameters that are sent in the query string. For example, imagine you have a page through which a user has identified him- or herself by typing a name in a text box. The browser inserts that name in a parameter inside the query list. You can instruct the output cache to cache different versions based on parameters in the query string. For example, users who identify themselves as "John Doe" can get a different version of cached content than can users who identify themselves as "Jane Smith." The VaryByParam attribute controls this behavior.

Table 1 shows a summary of these parameters.

Table 1. Summary of OutputCache Parameters
CacheProfileA stringName of a profile (found in web.config) to control output cache settings. Default is an empty string.
DurationnumberNumber of seconds the page or control is cached (required).
NoStoretrue falseSpecifies that the "no store" cache control header is sent (or not). Not available to user controls. Default value is false.




Manages which header and metatags are sent to clients to support caching; here are their meanings:

Any—page can be cached anywhere (default).

Client—cached content remains at browser.

Downstream—cached content is stored both downstream and on the client.

Server—content cached on the server only.

None—disables caching.
Sharedtrue falseDetermines whether user control output can be shared with multiple pages.
SqlDependencyA string representing a database/table name pairIdentifies a set of database and table name pairs on which a page's or control's output cache depends.
VaryByContentEncodingencodingsSpecifies a list of encoding strings separated by commas used to vary the output cache.
VaryByCustombrowser custom stringTells ASP.NET to vary the output cache by browser name and version or by a custom string; must be handled by an override of GetVaryByCustomString in Global.asax.
VaryByHeader* header namesA semicolon-delimited list of strings specifying headers that might be submitted by a client. Not available to user controls. Default value is an empty string (no headers).


param name
A semicolon-delimited list of strings specifying query string values in a GET request or variables in a POST request (required).

The following exercise illustrates creating separate versions of cached content based on how the user identifies himself or herself.

Varying cached content by query string parameters

  1. Returning to the OutputCache Web application, add a TextBox and a Button to the default.aspx page. Give the TextBox an ID of TextBoxName and the Button an ID of ButtonSubmitName. The TextBox will hold the client's name and will serve as the parameter controlling the number of cached versions of the page.

  2. Double-click the button to add a Click event handler. In the handler, respond to the user's request by displaying a greeting using the contents of the text box. Also, modify the processing time of the page loading by reducing the amount of time the current thread sleeps (or by commenting out that line):

    public partial class _Default : System.Web.UI.Page
    protected void Page_Load(object sender, EventArgs e)
    Response.Write("This page was generated and cached at: " +

    protected void ButtonSubmitName_Click(object sender, EventArgs e)
    Response.Write("<h2> Hello there, " +
    this.TextBoxName.Text + "</h2>");

  3. Increase the time that the content will be cached (this example uses 1 minute) so that you have time to change the contents of the TextBox to view the effects of caching. Also, include TextBoxName as the parameter by which to vary the content in the OutputCache directive.

    <%@ Page Language="C#" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default"

    <%@ OutputCache Duration="60" VaryByParam="TextBoxName" %>

  4. Add a Substitution control to the page following the TextBox and the Button. You can just drag one from the Toolbox onto the page. Use the SubstitutionSubstitution controls call back to a method on the code beside that displays arbitrary strings. Write a method in the code-beside class to handle the substitution. control to display the time of the request to compare it with the time displayed by the cached page.

    public partial class _Default : System.Web.UI.Page
    // Existing code ...
    protected static string SubstituteDateAndTime(HttpContext c)
    return "Request occurred at :" + DateTime.Now;

  5. Set the MethodName attribute of the Substitution control to the SubstituteDateAndTime method in the ASPX file, like this:

    <asp:Substitution ID="Substitution1" MethodName="SubstituteDateAndTime"
    runat="server" />

  6. Surf to the page and type in a name. Click the button to submit the form and note the time stamp of the page. Type a second name in the TextBox and click the button to submit the form. Note the time stamp. Then, type the same name you typed the first time. Click the button to submit the form. If you do all of this within the 60-second window, you should see the cached versions of the page, which you can discern using the time stamp displayed as part of each page. The following three graphics illustrate the caching varying by the value of the TextBoxName parameter. The first graphic shows the original request using a particular name in the TextBox. Notice that the request time shown by the Substitution and the time shown by the Page_Load method are the same.

The second graphic shows a request with a new value for the TextBoxName parameter. Notice that the request time shown by the Substitution and the time shown by the Page_Load method are the same this time as well:

The third graphic shows making a request to the page using the same name as the original request. Notice that the request time shown by the Substitution and the time shown by the Page_Load method are different. The request time is earlier than the time shown during the Page_Load method, meaning the page content was cached:

There are other ways to modify the VaryByParam attribute. One way is to use the word none, which means ASP.NET will cache only one version of the page for each type of request (for example, GET, POST, and HEAD). Using an asterisk (*) for VaryByParam tells ASP.NET to cache as many different versions of the page as there are query string or POST body requests. The previous example caches as many different versions of the page as there are unique names typed by users into the name text box.

Using VaryByHeader in the OutputCache directive tells ASP.NET to generate a separate cache entry for each new header string that comes down. (For example, UserAgent and UserLanguage represent HTTP headers that can be sent by the client.)

You will cache a user control shortly. With the VaryByControl attribute, you can cache separate content versions for each page that has a user control with unique properties.

Finally, VaryByCustom tells ASP.NET to manage separate cache entries dependent on a couple of factors. The first factor is the browser types and versions. Alternatively, you can provide a custom GetVaryByCustomString method in Global.asax that tells ASP.NET to create separate cached versions of a page based on a custom defined string.

2. The HttpCachePolicy

The second way to manage the output cache is through the HttpCachePolicy, which is available from the Response class. Table 2 shows a portion of the HttpCachePolicy class.

Table 2. The HttpCachePolicy Class
AppendCacheExtensionAppends specified text to the Cache-Control HTTP header
SetCacheabilitySets the Cache-Control HTTP header, which controls how documents are to be cached on the network
SetETagSets the ETag HTTP header to the specified string
SetExpiresSets the Expires HTTP header to an absolute date and time
SetLastModifiedSets the Last-Modified HTTP header to a specific date and time
SetMaxAgeSets the Cache-Control: max-age HTTP header to a specific duration
SetRevalidationSets the Cache-Control HTTP header to either the must-revalidate or the proxy-revalidate directives
SetValidUntilExpiresDetermines whether the ASP.NET cache should ignore HTTP Cache-Control headers sent by the client for invalidating the cache
SetVaryByCustomSpecifies a custom text string for managing varying cached output responses
VaryByHeadersParameter list of all HTTP headers that will be used to vary cache output
VaryByParamParameter list received by a GET (query string) or POST (in the body of the HTTP request) that affects caching

When you set up an OutputCache directive, you tell ASP.NET to populate this class during the Page class's InitOutputCache method. The Response object makes the HttpCachePolicy available through its Cache property. The name Cache is unfortunate because you might easily confuse it with the application data cache. Perhaps CachePolicy would have been a better name for the property to avoid such confusion. In any case, you can use the HttpCachePolicy class to control the behavior of server-side output caching as well as the headers used for content caching. You can also use the OutputCache directive to control some of the same aspects as the HttpCachePolicy class. However, some features, such as sliding the expiration date or changing the "last modified" stamp for a page, are available only through the HttpCachePolicy class.

For example, Example 1 shows a page fragment ensuring that all origin-server caching for the current response is stopped. It also sets the last modified date to the current date and time.

Example 1. Manipulating the output cache policy
public partial class _Default : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)

Response.Write("This page was generated and cached at: " +


3. Caching Locations

In addition to varying the number of cached versions of a page, you can tell ASP.NET where to cache the content. This is controlled through either the LocationHttpCachePolicy class's SetCacheability method. attribute in the OutputCache directive or by using the

ASP.NET supports several output caching locations that you can specify using the OutputCache directive:

  • Any Page can be cached by the browser, a downstream server, or on the server.

  • Client Page should be cached on the client browser only.

  • Downstream Page should be cached on a downstream server and the client.

  • Server Page will be cached on the server only.

  • None Disable caching.

With the HttpCachePolicy, you can also determine the location of the cached content programmatically. This is done through the HttpCachePolicy.SetCacheabilityHttpResponse.CacheControl property), which takes a parameter of the HttpCacheability enumeration. The enumeration is a bit easier to read than the attributes used in the OutputCache directive are. They include the following: method (or the

  • NoCache Disable caching.

  • Private Only cache on the client.

  • Public Cache on the client and the shared proxy.

  • Server Cache on the server.

  • ServerAndNoCache Specify that the content is cached at the server but all others are explicitly denied the ability to cache the response.

  • ServerAndPrivate Specify that the response is cached at the server and at the client but nowhere else; proxy servers are not allowed to cache the response.

4. Output Cache Dependencies

The contents of the application data cache in ASP.NET can be flushed because of various dependencies. The same is true of ASP.NET output caching. The response object has a number of methods for setting up dependencies based on cached content. For example, you might want to set up a page that renders data from a text file. You can set up a CacheDependency on that text file so that when the text file is changed, the cached output is invalidated and reloaded.

5. Caching Profiles

One of the problems associated with using the OutputCache directive directly is that the values become hard-coded. Changing the caching behavior means going in and changing the source code of the page. A feature added to ASP.NET 2.0 and later versions is the ability to add caching profiles. That way, setting the caching behavior variables is offloaded to the configuration file, and output caching becomes an administration issue and not a programming issue (as it should be).

The web.config file can include an outputCacheSettings section that contains a list of outputCacheProfiles. The outputCacheProfiles are simply key/value pairs whose keys are the output caching variables (such as Duration). When you mention the profile name in the OutputCache directive, ASP.NET simply reads the values out of the configuration file and applies them to the OutputCache directive.

The following exercise illustrates how to set up a cache profile instead of hard coding the values into the page.

Setting up a cache profile

  1. Add a cache profile to the site's web.config file. If web.config isn't already there, go ahead and add one to the project. Then, add a cache profile to web.config nested between the system.web opening and closing tags. Name the cache profile profile.

    <add name="profile"
    varyByParam="TextBoxName" />

  2. Change the OutputCache directive in the Default.aspx page to use the new profile:

    <%@ Page Language="C#" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default"

    <%@ OutputCache CacheProfile="profile" %>

  3. Surf to the page. It should work exactly as it did before when the caching values were hard-coded. That is, run the page, type a name, and note the date and time stamp. Type a new name and note the date and time stamp. Type the original name, submit it, and you should see the original cached page appear (as long as you complete the post within the specified time window).

Top 20
Building Android Apps: Web SQL Database (part 4) - Deleting Rows
Serialize to an In-Memory Stream
Exploring the T-SQL Enhancements in SQL Server 2005 : The WAITFOR Command
.NET Compact Framework : Font Selection
iPhone 3D Programming : HelloCone with Fixed Function
.NET Micro Framework : Weak Delegates
Algorithms for Compiler Design: RIGHT LINEAR AND LEFT LINEAR GRAMMAR
Silverlight : Capture a Webcam
Troubleshooting and Testing Network Settings
.NET Enterprise Services Technologies : BizTalk Server
Randomized Stack Space
Where Windows Malware Hides
IIS 7 Authentication
WCF Services : Data Contract - Hierarchy
Android’s Securable IPC Mechanisms
ASP.NET 4 in VB 2010 : The Security Controls
Becoming an Excel Programmer : Start and Stop
.NET Enterprise Services Technologies : Application Blocks and Software Factories
The SQL Server 2008 Configuration Manager
Programming Hashing Algorithms (part 1) - The HashAlgorithm Class