Cache Control for Fun and Profit


So you have a website and it’s really important. Maybe people are using it publicly and entering credit cards or something. What’s the worst thing that can happen? Well I’ll tell you, the next guy could come up and hit the back button and see everyone’s credit card numbers. Think it’s not plausible? I once went to the DMV near me and found a kiosk to renew my driver’s license. It was just a computer hooked up to the internet in a very poor kiosk mode. So the first thing I did was hit the unmarked backspace key and saw the last guy’s credit card number. Why did that happen? Improper cache-control!!! Sorry, that just came out.

I digress.

So you how you do it in .NET? I mean, we want to cache some things, but not others. Well it’s pretty easy, but in practice there are a few tricks. First, we want to cache static content (pictures, JavaScript files, etc) but we DO NOT want to cache our pages. So let’s setup static content caching in our web.config at the configuration level:

  <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />

That was easy enough, and it works! But we still have some other content (the content we want secured) marked as “private” in the caching, that’s bad. So we’ll fix that by using the powers of Global.asax.cs!

protected void Application_EndRequest(Object sender, EventArgs e)
  if ((Response.Headers["Cache-Control"] ?? "") == "private")
    // Stop Caching in IE
    // Stop Caching in Firefox

So we are now checking for things that are marked “private” cache and making them expire immediately. But why am I not using Response.CacheControl? It turns out that Response.CacheControl is not as responsive as I would like:

Not the same

As you can see, Response.CacheControl thinks the static content is “private” where in reality it is “max-age”. Boo. But by directly checking the Response.Headers we will find the correct value and can check for it. This results in epic win!