ASP.NET 2.0 - Post Cache Substitution

Posted on 6/30/2006 @ 8:48 PM in #Vanilla .NET by | Feedback | 16194 views

Fragment Caching - where you cache a user control, so the entire page isn't cached, but the small portion of the page you wanted to be cached, is cached.

Well, Post-Cache Substitution is the exact opposite of that - the entire page is cached, except that little teenie weenie that you want to keep dynamic. It is implemented as the HttpResponse.WriteSubstitution method.

public void WriteSubstitution (HttpResponseSubstitutionCallback callback)

Per MSDN - "HttpResponse.WriteSubstitution allows insertion of response substitution blocks into the response, which allows dynamic generation of specified response regions for output cached responses",

... which in english means, when the ASP.NET page renders, your method which you passed in as the HttpResponseSubstitutionCallback delegate is called (callback?) to get the dynamic content, which is then inserted into the cached content and voilla - you got Post-Cache substitution. Cool eh? :)

Now here's the catch - the method that will sit inside HttpResponseSubstitutionCallback delegate instance, has to be either static or global or basically "instantiated and ready to eat". Why? Because ASP.NET will need to be able to call it without actually instantiating the page (i.e. when fetching from cache). The signature of HttpResponseSubstitutionCallback is quite straightforward -

public delegate string HttpResponseSubstitutionCallback (HttpContext context)

So a sample function could be -

public static string GetMyContent(HttpContext context)
   return "<b> This blog rocks </b>" ;

And how you'd hook it up inside your page is like this -

protected voide Page_Load(object sender, EventArgs e)
   Response.WriteSubstitution(new HttpResponseSubstitutionCallback(GetMyContent)) ;

But wait a minute - we're talking with the "Response" object - whatever happened to the fancy ASP.NET object model that we should have been using? Yeah I know it sucks, but for Post-Cache substitution, you hafta work with the Response object and not the object model. One explanation of this implementation could be - You don't really have the object model without instantiation the page (i.e. when fetching it out of the cache) - heh :) that makes sense.

But you could always wrap the substitutable content inside your own control, or heck ASP.NET 2.0 even comes with a generic substitution control that looks like this -

<asp:Substitution ID="MonkeyMan" runat="server" MethodName="GetMyContent" />

WOOHOO !! :) - now that's more elegant and now you don't need that programmatic Page_Load hookup either. The downer here is, you don't see cached content at design-time, but that isn't such a big deal now is it?

Sound off but keep it civil:

Older comments..

On 1/31/2007 4:00:27 PM egor598 said ..
I have tried to use post cache substitution control and it seems it's not possible to use Session state because it's not passed in HttpContext object. Do you any workarounds for this?


On 2/13/2007 1:06:22 PM Ahmet BUTUN said ..
I have got the same problem with "egor598". How can I pass Session object to HttpResponseSubstitutionCallback method ?

On 1/20/2009 6:57:38 AM firoz said ..
Everything looks cool with substitution but I had an issue it always write the return string on top of the page which something I don't want. Is there any way where I can capture the string return by the substitution method on client side then I can place those dynamic values according to my requirements

On 11/11/2010 10:02:36 AM Urbain said ..
If others got the same problem as firoz, one solution would be to create a user control which acts as a container and place the user control on the page. At the user controls Page_Load event you can call the WriteSubstituion method to write content into the container.

On 3/28/2011 9:05:09 AM ricky said ..
there is no doubt that cache is a wonderful tool as far performance of the app is concerned. but it has some limitations as well. for example due to its stand alone and in process nature, it is only good for smaller web farms, but when you have an app where number of servers are two or more, it may ends up with some performance and scalability issues. here this post as a reference,