25

I built a MVC3 app, the applicaiton have lot of pages, now because security issues I need to add the no-cache setup in http headers, Is any easier way to do it? if we can modify one place then it will working for entire application, it will be perfect.

Can you guys help me out?

abatishchev
  • 92,232
  • 78
  • 284
  • 421
Harry Liu
  • 361
  • 1
  • 4
  • 8
  • I've edited my answer to use the `Response.Cache.SetCacheability()` method instead of setting headers manually. Tested in Fiddler and working as expected. – Marko Aug 17 '11 at 04:46

5 Answers5

36

How about setting the Headers inside the Application_PreSendRequestHeaders event in Global.asax?

EDIT You can use Response.Cache.SetCacheability rather than setting the Headers directly.*

void Application_PreSendRequestHeaders(Object sender, EventArgs e)
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
}

Tested in Fiddler.


Alternative way by setting the Headers manually.

void Application_PreSendRequestHeaders(Object sender, EventArgs e) {
    Response.Headers.Set("Cache-Control", "no-cache");
}
Marko
  • 68,081
  • 26
  • 118
  • 153
  • 12
    That is WAY too much no-caching! If you do that you'll no-cache all javascript, css, icons, etc. and do quite a number on your bandwidth and responsiveness. – Scott Stafford May 02 '13 at 15:29
  • 2
    @ScottStafford read OPs request "if we can modify one place then it will working for entire application, it will be perfect." Obviously, some files can be filtered but that's not what was requested. – Marko May 02 '13 at 20:57
  • 4
    I know he said it. I didn't -1 or anything, but I wanted to make sure he (and any other readers) knew what the ramifications were of such a heavy-handed approach. Throw in a test for "is this an aspx file" and it's much more widely applicable. – Scott Stafford May 03 '13 at 02:56
  • @ScottStafford, that (.aspx filter) doesn't really work in MVC, but a similar filtering should be done. – ps2goat Nov 08 '13 at 22:46
14

Alternative for those wanting method/action or class/controller wide no-cache

[OutputCache(Location = OutputCacheLocation.None)]
public class HomeController : Controller
{
...
}

As explained here:

OutputCacheLocation Enumeration

None : The output cache is disabled for the requested page. This value corresponds to the HttpCacheability.NoCache enumeration value.

HttpCacheability Enumeration

NoCache - Sets the Cache-Control: no-cache header....

KCD
  • 8,614
  • 3
  • 57
  • 66
  • The ASP.NET output cache is not the same as the no-cache HTTP header, which OP is asking about. – Mike Marynowski Jan 17 '13 at 15:52
  • @MikeMarynowski yes but are you sure? I believe None means neither server nor the client and produces "Cache-Control: no-cache" header for the client – KCD Jan 17 '13 at 21:39
  • ["None : The output cache is disabled for the requested page. This value corresponds to the HttpCacheability.NoCache enumeration value."](http://msdn.microsoft.com/en-us/library/system.web.ui.outputcachelocation(v=vs.100).aspx) ... ["NoCache - Sets the Cache-Control: no-cache header...."](http://msdn.microsoft.com/en-us/library/system.web.httpcacheability(v=vs.100).aspx) – KCD Jan 17 '13 at 21:44
  • Hmmm, that's interesting, I've never seen this used to prevent client-side caching but I think I stand corrected. I wonder why this isn't used and suggested more often if that's the case - I almost exclusively see the suggestion to use Response.Cache.SetCacheability. Your way seems much more MVC-esque. – Mike Marynowski Jan 26 '13 at 11:15
  • If you can edit your answer to add a line about that I'll upvote - it locked the downvote unless the answer is edited. – Mike Marynowski Jan 26 '13 at 11:18
2

Set up a global filter.

public class MvcApplication : System.Web.HttpApplication
{

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new NoCacheGlobalActionFilter());
    }    
}

public class NoCacheGlobalActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        cache.SetCacheability(HttpCacheability.NoCache);

        base.OnResultExecuted(filterContext);
    }
}

http://dotnet.dzone.com/articles/output-caching-aspnet-mvc

stuartdotnet
  • 2,600
  • 3
  • 31
  • 35
1

I recommend that these calls be limited to non-GET requests, to avoid losing the benefit of cache on GETs. The following ensures that even aggressive caching browsers like iOS 6 Safari will not cache anything that is not a GET request.

I use a Controller base class that all of my controllers inherit from for a number of reasons, and this served well in that my Initialize override can handle setting my caching headers conditionally.

public class SmartController : Controller
{
    ...
    public HttpContextBase Context { get; set; }

    protected override void Initialize(System.Web.Routing.RequestContext requestContext)
    {
        Context = requestContext.HttpContext;

        if (Context.Request.RequestType != "GET")
        {
            Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        }

        base.Initialize(requestContext);
        ...
    }
...
}
Jim Speaker
  • 1,103
  • 7
  • 27
  • Setting cache policy based on HTTP verb is not going to be sufficient for a wide variety of apps. Let's say you have a page where you use a GET and a querystring to load hospital patient data? You don't want that page cached. – Larry Silverman Jul 08 '16 at 21:14
  • Larry, in that case you certainly would not want to implement base controller logic like I have suggested here. :) – Jim Speaker Jul 11 '16 at 21:37
1

I would do it in IIS itself (assuming you are using that), or the web.config:

<configuration>
   <system.webServer>
      <staticContent>
         <clientCache cacheControlMode="DisableCache" />
      </staticContent>
   </system.webServer>
</configuration>

Less code is better code.

The setup is slightly different based on the version of IIS.

See here for more info.

RPM1984
  • 69,608
  • 55
  • 212
  • 331
  • Does that configuration only apply to static content (img, js, css, etc.), or is the name just a bit misleading? It's not quite clear from the IIS website. – Troy Hunt Aug 17 '11 at 05:12
  • @Troy - i *think* it's everything. Pretty easy to test, just check the response headers in fiddler/firebug/etc – RPM1984 Aug 17 '11 at 06:22
  • 2
    Controlling cache from the application seems more appropriate to me, because I expect most people would want caching of static content. Also, I wouldn't say your solution requires less code :-) . – theDmi Sep 24 '12 at 13:00
  • It does require less code. It's just a web.config change. In other words, it doesn't have to be recompiled and patched, and it can go to the root web.config and apply site-wide if necessary. Thanks, BTW, just what I was looking for! – PhilDearmore Sep 03 '13 at 20:06