Programming Microsoft ASP.NET 4 - Dino Esposito [400]
Vary by Headers
The VaryByHeader attribute and the HttpCachePolicy’s VaryByHeaders property allow you to cache multiple versions of a page, according to the value of one or more HTTP headers that you specify.
If you want to cache pages by multiple headers, include a semicolon-delimited list of header names. If you want to cache a different version of the page for each different header value, set the VaryByHeader attribute to an asterisk (*). For example, the following declaration caches for one-minute pages based on the language accepted by the browser. Each language will have a different cached copy of the page output.
<%@ OutputCache Duration="60" VaryByParam="None"
VaryByHeader="Accept-Language" %>
If you opt for a programmatic approach, here’s the code to use that leverages the VaryByHeaders property of the HttpCachePolicy class:
Response.Cache.VaryByHeaders["Accept-Language"] = true;
If you want to programmatically vary the pages in the cache by all HTTP header names, use the VaryByUnspecifiedParameters method of the HttpCacheVaryByHeaders class:
HttpCacheVaryByHeaders.VaryByUnspecifiedParameters();
The preceding code is equivalent to using the asterisk with the VaryByHeader attribute.
Vary by Custom Strings
The VaryByCustom attribute in the @OutputCache directive allows you to vary the versions of page output by the value of a custom string. The string you assign to the VaryByCustom attribute simply represents the description of the algorithm employed to vary page outputs. The string is then passed to the GetVaryByCustomString method, if any, in the global.asax file. The method takes the string and returns another string that is specific to the request. Let’s examine a concrete example—varying pages by the type of device that requests the page. You use, say, the string device with the VaryByCustom attribute:
<%@ OutputCache Duration="60" VaryByParam="None" VaryByCustom="device" %>
Next, you add your application-specific GetVaryByCustomString method in the global.asax file. Here’s a possible implementation:
public override String GetVaryByCustomString(HttpContext context, String custom)
{
if (custom == "device")
return context.Request.Browser.Type;
return base.GetVaryByCustomString(context, custom);
}
The output of the page is varied by user agent string. You can use any other custom information as long as the information is available through the HttpContext class. You can’t use information that is known only when the page is loaded, such as the theme. Custom information gathered by a custom HTTP module might be used if the HTTP module parks the information in the Items collection of the HttpContext object, and as long as the HTTP module is triggered before the request to resolve the page output cache is made.
Nicely enough, the feature just described—varying pages by user agent strings—has been natively available since ASP.NET 1.0. The only difference is that it uses the keyword browser instead of device. In other words, the following code is perfectly acceptable and leverages the implementation of GetVaryByCustomString on the base HttpApplication class:
<%@ OutputCache Duration="60" VaryByParam="None" VaryByCustom="browser" %>
You use the SetVaryByCustom method on the HttpCachePolicy class if you don’t like the declarative approach:
Response.Cache.SetVaryByCustom("browser");
Caching Portions of ASP.NET Pages
The capability of caching the output of Web pages adds a lot of power to your programming arsenal, but sometimes caching the entire content of a page is not possible or it’s just impractical. Some pages, in fact, are made of pieces with radically different features as far as cacheability is concerned. In these situations, being able to cache portions of a page is an incredible added value.
If caching the entire page is impractical, you can always opt for partial caching. Partial caching leverages the concept of ASP.NET user controls—that is, small, nested pages that inherit several features of the page. In particular,