Cache for speed with .Net
The better you can make your users experience the more they will like to use your site. One aspect is of this experience is speed.
Following on from my previous post, we will look at adding simple caching to our project for another quick win, this is just one method of many. Caching really depends on the size and type of your application and hosting environment.
The tools
- Microsoft Visual Studio 2010 or Trail editions (Download via Web platform installer)
- Mmm thats it!
Lets start
We need to create a HttpModule to interface and handle our events.
Here we go again. “File > New Project > Windows > Class Library”
Create a new class and call it eModule.cs , the name is not really important, it’s just what fits your best.
Now we should have something that look likes this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ExpiresModule
{
class eModule
{
}
}
Lets tidy up our “using”, and add the ones we will need.
Remove :
using System.Collections.Generic; using System.Linq; using System.Text;
And add :
using System.Web; using System.IO;
Now lets inherit from IHttpModule and set up the basic structure of the HttpModule. First we need to add “System.Web” to our references so we can work with IHttpModule.
Time to set up the basic frame work for our Caching module, We will need to add the Init() and if we want to be nice the Dispose() methods.
namespace ExpiresModule
{
public class eModule : IHttpModule
{
public void Dispose()
{
// Dispose();
}
public void Init(HttpApplication context)
{
}
}
}
Great thats a good start. Now we have to decide which file types we wish to cache. Lets go for static file types.
private readonly static string[] CACHCED_STATIC_TYPES = new string[] {".jpg", ".gif", ".png",".css", ".js" };
I think that covers the basics. Now to work with HttpContext to deal with our item request to out static file types and respond back and set the expire headers for our static types.
void context_AcquireRequestState(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (context != null & context.Response != null)
{
string fileExtension = Path.GetExtension(context.Request.PhysicalPath).ToLower();
if (context.Response.Cache == null || Array.BinarySearch(CACHCED_STATIC_TYPES, fileExtension) < 0)
return;
HttpCachePolicy cache = context.Response.Cache;
cache.SetExpires(DateTime.Now.AddYears(30));
cache.SetMaxAge(TimeSpan.FromDays(365.0 * 3.0));
}
}
The important thing about caching it setting the cache date far enough in the future, YSlow and Google Page speed do like to be at least a couple of months. You might be thinking, what if I change my CSS file, I want to make sure the user see the latest version? I’ll cover that in a future post.
Time to add our event listener to Init() to trigger our function on request of a page load.
public void Init(HttpApplication context)
{
context.BeginRequest += context_AcquireRequestState;
}
Well thats about it for our ExpiresModule. We should now have something like this:
using System;
using System.Web;
using System.IO;
namespace ExpiresModule
{
public class eModule : IHttpModule
{
private readonly static string[] CACHCED_STATIC_TYPES = new string[] {".jpg", ".gif", ".png",".css", ".js" };
public void Dispose()
{
// Dispose();
}
public void Init(HttpApplication context)
{
context.BeginRequest += context_AcquireRequestState;
}
void context_AcquireRequestState(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (context != null & context.Response != null)
{
string fileExtension = Path.GetExtension(context.Request.PhysicalPath).ToLower();
if (context.Response.Cache == null || Array.BinarySearch(CACHCED_STATIC_TYPES, fileExtension) < 0)
return;
HttpCachePolicy cache = context.Response.Cache;
cache.SetExpires(DateTime.Now.AddYears(30));
cache.SetMaxAge(TimeSpan.FromDays(365.0 * 3.0));
}
}
}
}
How do I use it?
Once you have compile this module, we can add the release DLL as a reference in to any of your other projects.
Followed by a declaration in your web.config to initialise the HttpModule.
<httpModules>
<add name="ExpiresModule" type="ExpiresModule.eModule, ExpiresModule"/>
</httpModules>
Finally
I hope this might help someone, I’m sure a bit more work could make it better.
If you have access to IIS then the above code could be avoided and caching static types could be configure in IIS. You may also want to investigate “ETags” and “clientCache” in web.config.
If you found this helpful and would like to buy me a beer to say thanks, please 
Full project code is available for download (See right hand navigation)


