Programmatically clearing the ASP.Net cache for Web Forms and MVC pages


Page level caching for ASP.Net webforms and MVC websites is pretty awesome, because it allows you to implement something that's quite complex; multilevel caching, without having to really understand too much about caching, or even write much code. But what if you want to clear a cached page before it's due to expire?

There are only two hard things in Computer Science: cache invalidation and naming things.

- Martin Fowler

What page caching aims to achieve

When developers turn to caching pages in their websites, usually it's because of one thing; the need for speed. When our code bases start to require continual requests to a data store, be it disk or database, that doesn't change too much overtime, caching is usually the first hammer we turn to to minimise fetching from slower stores.

ASP.Net Web Forms and ASP.Net MVC both make this a pretty trivial thing to do by hiding the complexity of cache providers behind simple attributes to either your .aspx pages or controller actions:

WebForms page output caching example:

<%@ OutputCache Duration="300" VaryByParam="productId" %> MVC controller caching:

[OutputCache(Duration = 300, VaryByParam = "prodId")]
public ActionResult ProductDetails(string prodId)

The above is awesome because it's simplicity, but you'll notice one key thing here:

I've set my cache expiry to 300 seconds.

This is primarily because I want the content to pull from the source now and then just in case something has changed.

I've used 300 seconds, but really the time may be inconsequential – I've just set it to an arbitrary number that I deemed would meet my needs.

This doesn't really use the cache as well as it could be used in many scenarios, the primary one being during a period where my site isn't being updated, and the content only changes once every few days/weeks/months.

The .Net tooling attempts to allow for these situations by having support for providers like the SQLCacheDependency you can add to your application.

But the SQL cache provider or even a CustomCacheProvider don't give you the fine grain control you really want: being able to programmatically remove page, control, action or child-action level cached pages.

Like most great things: simple and elegant does support this out of the box – you just don't hear about it much.

You can tell the runtime to remove cached pages and controls simply by using a very simple recursive API that refers to it's relative Url.

// remove any webforms cached item with the wildcard default.aspx*

// just remove the webforms product page with the prodId=1234 param

// remove my MVC controller action's output
HttpResponse.RemoveOutputCacheItem(Url.Action("details", "product", new { id = 1234 }));

You'll notice for the MVC page's cache reference I used the Url.Action helper, and I recommend this, as it uses the same MVC routing as the cache provider – usually taking the first route found. Using the Url.Action helper means your provided Url follows the same path in reverse to that of the cache provider.

For MVC child actions there is currently no way that I know of clearing individual control's caches. MVC controller child actions are stored in the ChildActionCache.

To clear the entire child action cache you can do the following:

OutputCacheAttribute.ChildActionCache = new MemoryCache("NewRandomStringNameToClearTheCache");

Obviously this is a pretty aggressive approach, but if you would like to do this in a more granular fashion, try the open source project MVC Doughnut caching instead.