ASP.Net WebForms – Partial Page Caching With The Substitution Control

comments

Often when using built-in ASP.Net WebForm Caching to speed up a page’s output time, people feel pigeon holed into either caching the whole page, or setting up output caching for the majority of controls on the page individually. An often overlooked approach is to use the Subsitution control. This allows you to have your cake and eat it too by caching the whole page, and yet still updating a part of the page on every load.

The Usual Caching Story

When you are looking to cache a WebForms page you often start out with Page level caching and cache the whole page in its entirety to get the best bang for buck performance wise:

image

Then as your web application grows, and you add dynamic elements to a page, you have to change your caching configuration to match. This usually ends with a decision:

  1. Leave your page caching level to “entire page” caching, however set the length of the cache’s expiry to a short period of time so that your dynamic content is updated frequently (or if your caching relies on a dependency other than time, clear your cache more often).

    OR
  2. Move all the content of your page that you want to cache into user controls, and set their caching dividually or to a caching profile.

image

An (Often Overlooked) Alternative

The Substitution control is an often overlooked part of the .Net WebForm world. The above situation (setting up cached user controls) is in my experience, 9 times out of 10 the solution that developers use. There is another option though, and it allows you to cache your entire pages content, avoid a lot of the processing time that the majority of the page’s events take to complete and yet still keep sections dynamic – the Substitute control.

The Substitution control is very similar to a Literal and operates as a place holder for content, however the only property the control has it has is a called MethodName, and is the name of the Page method that will be called to fill the controls surface.

image

This allows us to cache the entire page, and get the speed advantage that comes from doing this, however we also gain the ability to server dynamic content into placeholders.

The method that you name in the MethodName property needs to be accessible in the pages code-behind, return a static string and take a single parameter in the form of an HttpContext.

static string SubstitutionMethod(HttpContext context)
{
    return "My Content";
}

A Live Example

A live example of the usage of this control as i talk about it above is below. I have a literal that shows the current DateTime, and Substitution control that calls a method that returns the same. The entire page is cached, so as you refresh the page after it’s first load the first DateTime will stay static, however on each subsequent load the second displayed DateTime will refresh.

<%@ Page Language="C#" %>
<%@ OutputCache Duration="60" VaryByParam="none" %>
<script runat="server">
    void Page_Load()
    {
        staticDateTime.Text = DateTime.Now.ToString();
    }
    static string CurrentDateTime(HttpContext context){
        return DateTime.Now.ToString();
    }
</script>
<html>
<body>
    <form id="form1" runat="server">
    DateTime at first load: <asp:Literal 
    ID="staticDateTime" 
    runat="server" /><br />
    DateTime at last load: <asp:Substitution 
    ID="dynamicDateTime"
    MethodName="CurrentDateTime"
    runat="server" />
    </form>
</body>
</html>