Does MVC OutputCaching take preference over setting cache response headers?
Asked Answered
A

2

8

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?

Aquatint answered 2/11, 2010 at 13:26 Comment(0)
A
2

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.

Aquatint answered 3/11, 2010 at 12:28 Comment(0)
B
7

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?

Babb answered 2/11, 2010 at 13:34 Comment(1)
This is only partly true. The OutputCacheLocation.Any value from MSDN: "The output cache can be located on the browser client (where the request originated), on a proxy server (or any other server) participating in the request, or on the server where the request was processed." So what will happen to the client cache in this case?Aquatint
A
2

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.

Aquatint answered 3/11, 2010 at 12:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.