Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does MVC OutputCaching take preference over setting cache response headers?

This question is related to my other question.

I have an MVC application with caching disabled for all controller actions. I do this by setting cache response headers in Application_BeginRequest:

    protected void Application_BeginRequest()
    {
        HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
        HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        HttpContext.Current.Response.Cache.SetNoStore();
    }

There is single controller action for which I do want caching enabled. I have decorated this action with the OutputCache attribute:

[OutputCache(Duration = 300, VaryByParam = "id")]

What happens now for this action? Does it get cached because of the OutputCache attribute, or is it not cached because of the response headers?

-- EDIT --

As it seems, the response headers take preference. So my question becomes: how can I enable cache for single controller actions? Overwrite the response headers again?

like image 665
Carvellis Avatar asked Nov 02 '10 13:11

Carvellis


2 Answers

The two things are separate; the response cache is primarily looking at what the client sees - what they will use without hitting the server, or what modified-date they will send up to the server.

OutputCache, however, is focused at the server; the request will still happen (unlike something cached at the client), but it is possible (hopefully likely) that your method won't be called: instead, the cached version will be returned.

So: it is not cached at the client; a HTTP request is made, and (for requests within 5 minutes, for the same id, memory permitting) the cached version is returned from the server (typically reducing IO and CPU load at the server). Make sense?

like image 181
Marc Gravell Avatar answered Sep 27 '22 19:09

Marc Gravell


The response headers enforce the cache control. The solution was not to set response headers for controller actions that require caching. Instead of using OutputCache, I'm now using a custom cache attribute that also sets an ISCACHED key in the request items dictionary. The code snippet from my question was changed to this:

    protected void Application_EndRequest()
    {
        if (HttpContext.Current.Items["ISCACHED"] == null)
        {
            var cache = HttpContext.Current.Response.Cache;
            cache.SetCacheability(HttpCacheability.NoCache);
            cache.SetNoStore();
            cache.SetExpires(DateTime.Now.AddDays(-1));
        }
    }

I had to move this from BeginRequest to EndRequest, to allow actions to set the ISCACHED request item first. If it is set, a controller already handled caching for this request, otherwise caching is disabled.

like image 23
Carvellis Avatar answered Sep 27 '22 19:09

Carvellis