
When building a web application, one of the most important aspects of the its usability is performance. To be more exact, how quickly the app responds to and process requests for information. One of the best ways to help improve your app's performance is by caching some of the data the server/app needs to render the requested resource [in this a web page]. For a quick-and-dirty intro to what caching is all about, check out this Wikipedia entry.
Caching with ASP.NET
The ASP.NET framework provides three types of caching for web-based applications:
- Page Level Caching (called Output Caching)
- Page Fragment Caching (often called Partial-Page Output Caching)
- Programmatic or Data Caching
In this post I'll cover one of the finer points of Page Fragment Caching - using the PartialCachingAttribute class and its varyByCustom parameter to provide customized caching of User Controls.
The PartialCachingAttribute class encapsulates the cache settings the ASP.NET framework uses to perform output caching of a control. All that is needed is to apply the attribute to the class declaration of the control's code-behind file, and supply parameters to tell the framework how to vary the caching of the control. The most common parameter used to vary the cache is duration, and as its name implies this parameter determines the amount of time, in seconds, that the control will be cached. A much less obvious way to vary the cache is through the varyByCustom parameter.
What is the varyByCustom parameter?
According to MSDN documentation, it is a string that represents a custom output caching requirement. Clear as mud, isn't it? Perhaps this will help... when the string "browser" is passed, the cache will be varied based on the requesting web browser's name and major version number as determined by the browser's user-agent. This implementation is provided for free by the framework, but isn't exactly what I would call custom. For instance, you may want your cache to be varied based on some internal state and/or property of your application. I'll use an example to demonstrate...
An Example
First, we will pretend that your application is an online RSS aggregator site where a user can login to see/read all of the feeds to which he/she subscribe. Now lets also say that you have a control (we'll call it FeedList) that displays a list of all of the feeds to which a given user subscribes. It would be nice to be able to use output caching on the FeedList control since the feeds to which a user subscribes is not likely to change with each request to the application. For this example, we will cache the control for 45 seconds and vary the cache based on the logged in user's ID. Basically this means that for any given user, we will cache the rendered output of the FeedList for 45 seconds. So, how do we do this... Just apply the PartialCachingAttribute to the control like so...
[PartialCaching(45,null,null,"UserId",false)]
public class FeedList : System.Web.UI.UserControl
{
// Do some cool suff here...
}
The key thing to notice here is the 4th parameter in the PartialCachingAttribute constructor, "UserId". This string is being passed as the varyByCustom parameter and will allow the ASP.NET framework to vary our cache based on the logged in user's userId. However, this won't just happen auto-magically as might like... we need to do a little work first. Whenever we pass anything other than "browser" for this parameter, we need to override the GetVaryByCustomString method in the application's Global.asax file. This method will allow us to access the application to get the user's userId. The overridden method could look similar to this
public override string GetVaryByCustomString(
HttpContext context, string custom)
{
if(custom == "UserId")
{
return theApp.CurrentUserId.ToString();
}
return base.GetVaryByCustomString(context, custom);
}
And that's it! The FeedList control will now have its output cached by the ASP.NET framework using a custom set of requirements. For anyone interested in seeing the above in some real code, subText uses this very technique to cache several of the user controls needed to render the UI. You can get the latest code here (be sure to check out Haacked's quickstart guide), and then check out the HomePage & CachedColumnControl classes.