Output Caching in ASP.net MVC

Table of Contents

Although nowadays most of us have broadband connections, resource caching is important as loading a resource from your local HD is (by now) still faster than fetching it remotely. In this post I’d like to explore how to control the ASP.net MVC caching behavior and its effects when using ajax requests for retrieving data.

Default ASP.net MVC Caching Behavior

If you don’t specify anything at all and you have a plain normal action method like

…Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of the response are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache MAY cache the response.

As a result, the browser might cache such ajax request made by a JavaScript client, which most of the time might not be desired. Especially our beloved IE used a massive caching approach leading to strange effects.

Disabling Caching Behavior

Lets first take a look on how to completely disable caching.

Globally on the Server (Custom Approach)

If we want to completely disable any kind of caching behavior, we could employ a kind of brute force approach by implementing a custom global action filter that sets the corresponding headers:

Note the Cache-Control and Expires header that has been added. This will prevent any kind of caching, on the server as well as on the client side.

Globally on the Server (OutputCache)

But rather than creating a custom filter, why not just re-use something existing. ASP.net has already a build-in caching mechanism called OutputCache. It is quite powerful and I’ll go into more detail soon. As a result you could annotate your controller as follows

in order to prevent caching. Consequently the response headers contain a Cache-Control: public, max-age=0 header.

Attention, you could also specify the following in your web.config:

<caching>
<outputCache enableOutputCache="false" />
</caching>

However, this won’t prevent caching. Instead it just indicates that no kind of caching mechanism should be applied. By just disabling the output cache we get the default cache headers used by ASP.net MVC which falls back to Cache-Control: private, thus again opening the browser the possibility to cache requests.

On the Client-Side using jQuery

Beside disabling the cache on the server-side, you also have the possibility to control the caching behavior on the client-side. jQuery’s ajax - for instance - allows you to specify a cache flag. Lets look at its effects. Executing an ajax request with

The response parameters don’t vary. But note that jQuery adds an additional, random generated request parameter _=... which is used to enforce a cache invalidation.

Enable Caching

Before I illustrated how to disable caching behavior. Now I’d like to take a look on how to enable it.

On the Server Side

While you could easily write your custom caching attribute using action filters, there is no need at all. ASP.net has the OutputCache mechanism which also provides a OutputCacheAttribute that can be applied to Controller actions. For instance we could decorate our controller action like

Conclusion: Caching Where and When I need It

In a real world application you’d obviously expect to have a proper combination of disabling/enabling the cache where appropriate. This implies to have the possibility to use an approach where you define a global default which can be overwritten where needed.

The approach I applied is to enforce disabling of the cache on a global basis for then enabling it on an as-needed basis. That is, all our controllers inherit from a custom BaseController class which performs some additional common work. I then annotated that class as follows

This turns out to be quite powerful as the amount of custom code involved is kept at a minimum. If you’re interested in using the OutputCache mechanism I’d suggest you to also take a look at custom Cache Profiles.