About the author

Steven HarmanSteven Harman is a passionate developer who believes that writing great software isn't just a job, its a craft.

ASP.NET MVP

For recent posts and more about me, scroll to the bottom.

Subscribe

  • Subscribe to my feed. via RSS
  • Subscribe via email via email

Jobs

Badges

  • Subtext Project
  • Support Subtext
  • HiddenNetwork.com Banner

Custom Output Caching in ASP.NET

cache money

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.

What others are saying.

# re: Custom Output Caching in ASP.NET
Gravatar
May 19, 2006
Excellent article which gives a clear in sight towards VaryByCustom, the example choosen is really good.
# re: Custom Output Caching in ASP.NET
Gravatar i.netdeveloper
Mar 02, 2007
Nice article, helped me a lot.
Thanks
# re: Custom Output Caching in ASP.NET
Gravatar Steve Harman
Mar 05, 2007
Hey, glad I could help!
# re: Custom Output Caching in ASP.NET
Gravatar Christian
Sep 13, 2007
Thanks for the article. One question though. How would you access a protected page level variable in the Global.asax to do this? Say I had a list of cities (nothing on the querystring) that could change with a postback. Any ideas?

Thanks,
Christian
# re: Custom Output Caching in ASP.NET
Gravatar Bob
Oct 11, 2007
What is the difference between PartialCaching and OutputCaching of a user control?

In your example can we also use <%@ OutputCache Duration="45" VaryByCustom="UserID" %> at the top of the user control page?
# re: Custom Output Caching in ASP.NET
Gravatar Steven Harman
Oct 12, 2007
@Bob, The difference is that OutputCaching will cache the generated markup for the specified time, no matter what.

But PartialCaching allows you to vary whether or not the cached output is used, or the output is re-rendered for a given request depending on some variable you specify as a parameter to the attribute's .cctor.
# Caching In 10 Minutes
Gravatar Work vs. Play
Oct 25, 2007
This is some stuff I&amp;#39;ve been meaning to post to the wiki at work because I&amp;#39;ve had a lot of questions
# Caching In 10 Minutes
Gravatar Work vs. Play
Oct 26, 2007
This is some stuff I&amp;#39;ve been meaning to post to the wiki at work because I&amp;#39;ve been asked a lot
# re: Custom Output Caching in ASP.NET
Gravatar Teetotaller
Dec 03, 2007
I have a question - how do I remove user control cache entry for specific UserId?
# re: Custom Output Caching in ASP.NET
Gravatar Steven Harman
Dec 03, 2007
Teetotaller, I think your best bet is to build a Custom Caching rule... like I did above that makes sure to never cache the control for specific UserId. You could also look into combining Custom Output Caching with "Donut Caching" to get even more fine grained control.
# re: Custom Output Caching in ASP.NET
Gravatar Anas Ghanem
Dec 12, 2007
nice article
i want to know how can i remove the output cache per user in this case ????

did it work if i use
Response.RemoveOutputCacheItem(...
if yes, what is the parameter value to pass here??
Response.RemoveOutputCacheItem("??????")
Comments have been closed on this topic.