Prior to ASP.NET 1.x, if you wanted to implement any sort of caching in your Web-based application,
you were pretty much on your own. With ASP.NET 1.x, Microsoft provided many different caching options
built right in. No longer were you forced to roll your own caching solutions. In many cases,
implementing caching was now as simple as adding the OutputCache directive to the top of your ASP.NET Web page
and letting .NET do the rest. Only in complex scenarios were developers required to write any code.
With ASP.NET 2.0, caching can still be implemented as simply as it was in ASP.NET 1.x, but Microsoft has added a
number of features in order to make the caching support even more flexible and robust. In this article I'm going
to give you a quick overview of the new caching features in ASP.NET 2.0 and show you how to use them.
While the caching support in ASP.NET 1.x represented a good first step, with ASP.NET 2.0 caching support
for Web applications built on the Microsoft platform takes a giant leap forward.
Please note that I'm not really going to cover the caching support which existed in ASP.NET 1.x and has
been carried over to ASP.NET 2.0. In this article, I'm going to focus on the new caching
features in ASP.NET 2.0. Therefore, if you're not already familiar with the caching support that ASP.NET 1.x offered,
you may want to take a look at some of the following links:
There are four main new features that I'll be covering. They are:
SQL Cache Invalidation
Post-Cache Substitution
Fragment Caching API
Cache Configuration
SQL Cache Invalidation
I'll start with what was probably the most anticipated new feature in ASP.NET 2.0's caching support:
SQL Cache Invalidation. Let's assume you've got a web page which queries data from a database.
If this is data that doesn't change very often, then there's really no need to query the database
for the data each time a user requests the web page, so we decide to cache the data. The problem
then becomes, how long do we cache the data for? If we cache it for too short a period then we make
our web server work harder then it needs to. In the larger scheme of things, this will increase our
operating costs since the server won't be able to handle as many requests and we'll need to add
another server sooner then we really should. If, on the other hand, we cache the data for too long a period
then we risk users being presented with out of data information. How big a problem this is really depends on the
actual application and the data being cached, but it's generally not good to be showing users out of data
information.
So finding the optimal length of time for which to cache a certain piece of data is not an
easy task. It depends on a lot of factors. Some of those include -- how quickly the application needs to
respond to users, the amount of users it needs to support, how frequently the data in the database changes,
how quickly those changes must be reflected in the web pages, and what are the potential consequences of displaying
old data?
What if instead of us having to continually check to see if there have been any changes, we could simply ask
the database to tell us when there's been a change made. This is where SQL cache invalidation comes in. Instead of
just picking a length of time to cache our data for, with ASP.NET 2.0's SQL cache notification
we can set it up so that when the data is changed in the database, the cached version of the data is
automatically cleared.
There are two methods to implement SQL cache invalidation. The method you use depends mainly on what data
source you are pulling data from. For SQL Server 2005 you'll want to use notification-based
invalidation and for earlier versions of SQL Server (7.0 and 2000), you'll need to use polling-based invalidation.
I won't go into the details of how to set up SQL cache invalidation here, but you can find instructions in the
ASP.NET 2.0 QuickStart which is installed with the .NET Framework SDK or hosted online on Microsoft's ASP.net
web site: SQL Cache Invalidation
Post-Cache Substitution
Post-cache substitution is for that situation where most everything on a page can be cached except for one or two little
exceptions that must be handled dynamically. In ASP.NET 1.x, the only way to handle this type of scenario was to split
the page up into sections that could be cached and then make those into user controls. It worked, but it could be
really confusing because you had to sort of reverse your thinking about the problem. It was no longer "let's cache
everything but this one little section", but instead became "let's find everything we need to cache and
turn it into a user control so we can cache it." All of a sudden your page is split up into ten different user
controls and everything got complicated simply because we wanted to do something like put a current timestamp
at the bottom of the page.
Post-cache substitution is exactly what it says it is. We take something that has been already been cached and
simply substitute some dynamic data back into it. In effect, we are caching the whole page and then just executing
the one little part that we didn't cache.
There are two ways to implement post-cache substitution. You can either use the Response.WriteSubstitution
command or the <asp:Substitution> control. I've used both in the sample page listing below.
<p>
Current time (<code>Response.WriteSubstitution</code>):
<% Response.WriteSubstitution(New HttpResponseSubstitutionCallback(AddressOf GetTime)) %>
</p>
<p>
Current time (<code><asp:Substitution></code>):
<asp:Substitution ID="mySubstitution" runat="server"
MethodName="GetTime"
/>
</p>
<p>
This page was cached at:
<%= DateTime.Now.ToString() %>
</p>
</form>
</body>
</html>
Fragment Caching API
The method used most often to cache sections of a page is called fragment caching. Fragment caching is what I
described earlier where you move the sections to be cached into user controls and then set the
OutputCache directive at the top of the control to cache it.
This works fine in all versions of ASP.NET, but in ASP.NET 2.0, we now have access to the fragment caching API.
This means that we are no longer stuck just choosing a finite number of minutes to cache the control.
Now we can programmatically adjust the caching options.
Why would you want to do this? Let's say that we're building a control that displays some stock market data.
During trading hours this control needs to be updated fairly regularly. After trading stops however, we'd be just
as happy to cache the data until the next morning. There's no reason to hit the database for every request
for the control when we know that the data can't possibly have changed.
Below are a simple web page and user control which show how you can easily change how long a control is cached.
<p>
This page fragment was generated at: <%= DateTime.Now.ToString() %>
</p>
I simply take the value from a drop down list and use that to set how long the control is cached.
Don't let that fool you though. Your logic can be as complex as you need it to be. You can vary
caching of the control based on time, user input, data from a database, or really anything that
makes sense for your situation.
Cache Configuration
The last thing I'm going to discuss is improvements that have been made in caching configuration
in ASP.NET 2.0. There have been two main advances in this area: the ability to create and use cache
profiles and to set cache properties via your application's configuration files.
Cache Profiles
In ASP.NET 1.x you needed to set the length of time for which a file should be
cached via the OutputCache directive at the top of the file. This made changing
caching configuration relatively difficult because in order to change the setting you had to
modify the setting in each file which implemented caching.
In ASP.NET 2.0, you can define what are called cache profiles. This allows you to create named sets of settings
which are defined in your web.config file. Then if you find you need to make a change to one of
the profiles, all you need to do is edit the profile in the config file and the change is picked
up by all the scripts using that profile.
So, in the script above, all you'd need to do in order to change the length of time for which all the pages using the
"ProductsCacheProfile" profile would be cached is to change the value in the web.config file. Similarly,
in order to move a page from one profile to another, simply change the name of the profile referenced in the
CacheProfile property of the OutputCache directive at the top of the page.
Cache Configuration via Config Files
I'm just briefly going to mention this next item because it's not something most developers will be messing with too much, but
for those of you who need to, you can now modify caching parameters via ASP.NET's configuration files as well.
You can enable or disable output and fragment caching, modify a number of parameters and even specify
how much memory the system should allow caching to use. For those of you who will need to modify
these settings the following links should be helpful:
After reading this article, I hope you'll agree that the caching support in ASP.NET 2.0 has come a long way.
From simpler configuration and management to more flexible implementation and deployment,
Microsoft has added a number of features which help make using ASP.NET caching in your application easier then ever.
If you're not already using caching in your ASP.NET applications, isn't it about time you started?