ASP.NET v1.x introduced a powerful feature known as Partial Page Caching. This feature allowed developers to construct ASP.NET pages which were partly dynamic and partly cached. Regions marked as dynamic are executed on each request while areas marked as cached are executed only once and cached until a specific dependency is enforced. The cached regions are separated into user controls with appropriate cache directives, and the dynamic content either remains in the parent Page or is contained in user controls without cache directives.

This partial page caching approach works very well for scenarios where most of the page content is dynamic and/or it is easy to encapsulate cached content into isolated user controls. It does not work as well for the inverse scenario, when the majority of page content should be cached and only a small portion is to be dynamic. For example, consider a page of news stories extracted from a database, which contains a single rotating advertisement. In this scenario, the news stories (and surrounding page header, footer, and site navigation interface) might be easily cached, since they change relatively infrequently. However, the rotating advertisement should change on each page request, to display a random advertisement to each site visitor.

ASP.NET Whidbey introduces a new feature called Post-Cache Substitution, which is aimed at optimizing the development experience for this mostly-cached page scenario. Rather than requiring page developers to mark page regions (user controls) as cached, post-cache substitution allows them to output cache an entire page and then simply identify regions of the page that should be exempt from caching. It also allows control developers to prevent their rendering from from being cached. In the above example, an AdRotator control that takes advantage of post-cache substitution would be able to serve a different advertisement on each request even if its parent page were cached.

Using the Substitution API

Page developers can easily take advantage of post-cache substitution in their output-cached pages. A developer simply writes a method with a prescribed SubstitutionCallback signature that takes a single HttpContext parameter and returns a String, which is the content to substitute at a given location. The developer then calls Response.WriteSubstitution, passing the callback method as a parameter. The callback method can either be a static method on the containing Page or UserControl, or a static or instance method on another arbitrary object, and must be thread-safe.

<%@ OutputCache Duration="60" VaryByParam="none" %>  
<script language="C#" runat="server">    
public static String GetCurrentDate (HttpContext context) 
{     return DateTime.Now.ToString();   }  
... cached content ...  
<form runat="server">   
<% Response.WriteSubstitution 
(new HttpResponseSubstitutionCallback(GetCurrentDate)) %>  

On the first request to the page, WriteSubstitution performs these steps:

1.       Calls the HttpResponseSubstitutionCallback delegate to produce the output.

2.       Adds a substitution buffer to the response, which retains the delegate to call on future requests, as well as the first-time output from step 1.

3.       Degrades client-side cacheability from public to server-only, so that the will not be cached on the client, ensuring future requests to the page re-invoke the delegate.

On subsequent requests, the cache module intercepts incoming requests and retrieves the associated stored buffers. When writing the substitution buffer, the delegate is invoked to produce new output, which is written to the response.




Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s