Caching
Caching
NET
ASP.NET supports 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
Output Caching
Page level, or output caching, caches the HTML output of dynamic requests to ASP.NET Web
pages. The way ASP.NET implements this (roughly) is through an Output Cache engine. Each time
an incoming ASP.NET page request comes in; this engine checks to see if the page being
requested has a cached output entry. If it does, this cached HTML is sent as a response;
otherwise, the page is dynamically rendered, its output is stored in the Output Cache engine.
Output Caching is particularly useful when you have very static pages. It is easy to implement. By
simply using the @OuputCache page directive, ASP.NET Web pages can take advantage of this
powerful technique. The syntax looks like this:
The Duration parameter specifies how long, in seconds, the HTML output of the Web page should
be held in the cache. When the duration expires, the cache becomes invalid and, with the next
visit, the cached content is flushed, the ASP.NET Web page's HTML dynamically generated, and
the cache repopulated with this HTML. The VaryByParam parameter is used to indicate whether
any GET (QueryString) or POST (via a form submit with method="POST") parameters should be
used in varying what gets cached. In other words, multiple versions of a page can be cached if
the output used to generate the page is different for different values passed in via either a GET or
POST.
The VaryByParam is a useful setting that can be used to cache different "views" of a dynamic
page whose content is generated by GET or POST values. For example, you may have an ASP.NET
Web page that reads in a Part number from the QueryString and displays information about a
particular widget whose part number matches the QueryString Part number. Imagine for a
moment that Output Caching ignored the QueryString parameters altogether (which you can do
by setting VaryByParam="none"). If the first user visited the page with QueryString
/ProductInfo.aspx?PartNo=4, she would see information out widget #4. The HTML for this page
would be cached. The next user now visits and wished to see information on widget #8, a la
/ProductInfo.aspx?PartNo=8. If VaryByParam is set to VaryByParam="none", the Output Caching
engine will assume that the requests to the two pages are synonymous, and return the cached
HTML for widget #4 to the person wishing to see widget #8! To solve for this problem, you can
specify that the Output Caching engine should vary its caches based on the PartNo parameter by
either specifying it explicitly, like VaryByParam="PartNo", or by saying to vary on all GET/POST
parameters, like: VaryByParam="*".
Location allows the caching to occur on the server, on the client, on a proxy server in between.
The default is Any. If you always want server caching (which seems to me to be the most useful
choice), change the line to read:
<%@ OutputCache Duration="3600" Location="Server" VaryByParam="none"%>
VaryByCustom="customstring" Allows you to specify a string that will be passed to your code.
To make this useful, you must then override the GetVaryByCustomString method in the
Global.asax file. For example, place this line in your ASPX file:
<%@ OutputCache Duration="3600" Location="Server" VaryByCustom="Referer"
VaryByParam="none"%>
VaryByHeader allows you to cache based off of some field in the HTTP header sent by the client.
The classic example is based off the Accept-Language header line.
VaryByParam allows you to cache different versions based off of querystring or post field
parameters. So http://www.domain.com/foo.aspx?bar=baz would be cached separately from
http://www.domain.com/foo.aspx?bar=bletch
Data Caching
In simple terms data caching is storing data in memory for quick access. Typically information
that is costly to obtain (in terms of performance) is stored in the cache. One of the more common
items stored in a cache in a Web application environment is commonly displayed database values;
by caching such information, rather than relying on repeated database calls, the demand on the
Web server and database server's system resources are decreased and the Web application's
scalability increased. As Microsoft eloquently puts it, "Caching is a technique widely used in
computing to increase performance by keeping frequently accessed or expensive data in memory.
In the context of a Web application, caching is used to retain pages or data across HTTP requests
and reuse them without the expense of recreating them."
Cache["key"] = value; // In C#
The above code adds the item value to the data cache with the key “key”. The key is used to
reference the item at some later point. That is, in another ASP.NET Web page we can extract the
value inserted above by using:
value = Cache("key")
- or -
value = Cache.Get("key")
To explicitly remove an item from the data cache you can use the Remove method, specifying the
key of the cache item you want removed:
Cache.Remove("key")
If you wish to have the cache item evicted from the cache in an absolute time, say, five minutes
from when it was inserted into the cache, you can use the third form of the Insert method, whose
fourth parameter expects a DateTime value specifying the absolute time. The following code
illustrates how to add an item to the cache that will expire five minutes from when it was added
and has no cache dependencies:
In C# you would use null instead of Nothing to signify that you do not want a cache dependency.
Note that since we do not want to specify sliding time expiration, we set the last parameter to
TimeSpan.Zero. Whereas an absolute time specifies that the item should be evicted from the
cache at a specific time, the sliding time eviction parameter specifies that the cache item should
be evicted if it is not referenced in a certain timespan. That is, if we set the timespan parameter
to, say, TimeSpan.FromSeconds(30), the cache item will be evicted if it is not referenced within
30 seconds. If it is referenced within 30 seconds, it will be evicted if it's not referenced in another
30 seconds from when it was last referenced, and so on. An example of this would be:
Note that when using the sliding time expiration parameter, the absolute expiration parameter
value does not matter. That is, it is automatically set to DateTime.Now and has the sliding time
added to it to determine the absolute time the cache item should expire. Of course, if the item is
referenced within that time period, the calculation is redone and the absolute expiration time is
reset.
Before we move on to some examples, let's take a quick look at the CacheItemRemovedCallback
delegate. Recall that you can set this in the fourth overloaded form of the Insert method. The
CacheItemRemovedCallback specifies a function that is called when the item has been evicted
from the cache. To use the CacheItemRemovedCallback you need to first create a function that
has the definition:
The CacheItemRemovedReason is an enumeration that explains why the item was removed from
the cache. Its entries include:
1. DependencyChanged - the item was removed because its cache dependency was changed.
2. Expired - the item was removed because it expired (either by absolute or sliding time
expiration).
3. Removed - the item was explicitly removed via the Remove method.
4. Underused - the item was evicted by the cache because the system needed to free up
memory.
To add a CacheItemRemovedCallback function to an added cache item you will need to create the
appropriate function and a delegate variable that is wired up to the function, as shown below: