AspNET caching 10102/26/2011
Welcome to a multi-part series on ASP.NET caching. This first part addresses practical caching applications, the second part, implementing Adxstudio CMS Cache Key Dependencies, and the third part will be on Sql Caching and Dependencies. Throughout the series we will focus on implementing a medium-level cache setup that is practical for most applications.
You may be aware of caching, but you may not realize how much performance gain it can provide your Web site. As an example I will share my first experience using some simple .NET caching features.
I was coding a dynamic navigational menu based on a categorical tree structure where the top nodes could have infinite child nodes (e.g. some recursive processing which tends to be time consuming). The query itself was originally running at around 10 seconds using my test dataset, I then optimized the query down to as low as 2.3 seconds. However this was still too slow. I implemented PartialCaching and the page loaded as quickly as 0.12 seconds on my local workstation. Not a bad day’s optimization!
Even if your Web site takes several minutes to load the first time we will cover beginner and intermediate caching practices to help your pages load as quickly as technically possible. This post will also give you a succinct overview of the caching features that are available. In this post we will cover:
- Output caching, a shotgun approach, cache all output for a Page.
- Fragmentcaching, a more surgical approach and works best with server controls or user controls.
- Cache substitution, allows a substitute part of a cached page to still allow dynamic behavior.
The Cache Object
The cache object can be directly manipulated. It is basically a key/value storage object. At its lowest level you can simply add the following code to the Page_Load method of your page:
HttpContext.Current.Cache["test"] = System.Guid.NewGuid();
This method does not give us any sort of automatic expiration or dependencies though. We are also manually storing our data. I think we can do a little bit better. This next example shows how to directly manipulate the cache but set an absolute expiration of 15 seconds.
if (HttpContext.Current.Cache["test"] == null)
If you run this code on an Asp.NET page you will see that the cache automatically clears every 15 seconds and outputs a new guid. At its lowest level the cache is easily accessible and capable of direct manipulations. In the next few examples we will continue to explore automatic cache expiration and other cool features.
@OutputCache is set as a page directive, similar to @Register or @Page directives. You can apply the @OutputCache directive to a Page or a UserControl. All output is then cached depending on the parameters specified. We’ll just cover parameters to implement an intermediate caching system.
- Duration (int)—Time in seconds the cache will persist for until the page code runs again.
- Shared (bool) —A flag to determine if the output of a UserControl can be shared by parent pages. This parameter is not valid for a Page that implements @OutputCache.
- VaryByParam (string) —One of the many VaryBy[…] attributes. A different cache copy will be saved per the querystring parameter specified. An example is VaryByParam=”QuerystringVal1”, where the url is http://www.foo.com/Default.aspx?QuerystringVal1=true.
The above parameters will get you through most situations. Here is what a common @OutputCache directive looks like:
<%@ OutputCache Duration="2592000" VaryByParam="DN;page" %>
This directive caches the output for 15 minutes. A different cache copy will be kept for each variation of “DN” and “page” querystring parameters. So if page is static and DN has 1,000 variations, there will be 1,000 different cached versions of this output.
The PartialCaching attribute is similar to the @OutputCache directive. PartialCaching is also referred to as fragment caching. It is typically the practice of caching output for a UserControl, which is only a fragment of the entire output. You can apply @OutputCache and your UserControl is cached or you can add the PartialCaching attribute to the Codebehind. The nice thing about the PartialCaching attribute is that you can apply it to any class, even server controls. Here is an example of how to add PartialCaching:
// cached for 30 days
[PartialCaching(2592000, "DN", null, null, true)]
public partial class Leftnav : System.Web.UI.UserControl
protected void Page_Load(object sender, EventArgs e)
// Page code here
Here we have a class called “Leftnav” which inherits from the UserControl class. Directly above the class declaration we have a PartialCachingAttribute called PartialCaching(…). Here are the parameters for the PartialCachingAttribute above:
- Duration, set to 30 days
- VaryByParams, set to “DN”
- VaryByControls, Null
- VaryByCustom, Null
- Shared, true—this UserControl output can be shared by more than one page
You could have also add an @OutputCache directive that looks like this:
<%@ OutputCache Duration="2592000" Shared="true" VaryByParam="DN" %>
One of the real benefits of using the PartialCachingAttribute is that you can apply it to server controls. In the event that you are using cache key dependencies it may be advantageous to keep your caching code in the Codebehind. We will cover this in the next article.
I find that it has limited use and am addressing in this post in a limited way. I recommend that you be aware of its existence. Cache Substitution is the process of outputting dynamic content in a cached situation. This could come in handy if you want to show a user’s membership name or the current time and date (and have the rest of the page cached). Below is a quick example of how to implement cache substitution to output the current Datetime.
On your aspx page add:
<%@ OutputCache Duration="900" VaryByParam="none" %>
In your Codebehind add:
protected static string OutputTime(HttpContext context)
When you refresh the page you will see that even though the output is cached, your substitution control will always have the current Datetime.
Caching is for everyone. Most Web sites should use caching to reduce server load and increase Web site performance. Part of Google’s algorithm is the speed or performance of your Web site. According to Google Webmaster Tools you want your Web site to load in under 1.5 seconds. If your site makes lots of expensive database calls, caching will help your pages to load more quickly.
In the next section we will look at cache key dependencies, focusing on how they are used in Adxstudio CMS and how you can create custom controls which invalidate cached based on changes made by users. Cache key dependencies are exciting because you can increase your server resource savings by tackling the issue of caching in a more precise, surgical approach.