89

I'm after a definitive reference to what ASP.NET code is required to disabled browsers from caching the page. There are many ways to affect the HTTP headers and meta tags and I get the impression different settings are required to get different browsers to behave correctly. It would be really great to get a reference bit of code commented to indicate which works for all browsers and which is required for particular browser, including versions.

There is a huge amount of information about this issue there but I have yet to find a good reference that describes the benefits of each method and whether a particular technique has been superseded by a higher level API.

I'm particularly interested in ASP.NET 3.5 SP1 but it would be good to get answers for earlier version as well.

This blog entry Two Important Differences between Firefox and IE Caching describes some HTTP protocol behaviour differences.

The following sample code illustrates the kind of thing I am interested in

public abstract class NoCacheBasePage : System.Web.UI.Page
{
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        DisableClientCaching();
    }

    private void DisableClientCaching()
    {
        // Do any of these result in META tags e.g. <META HTTP-EQUIV="Expire" CONTENT="-1">
        // HTTP Headers or both?

        // Does this only work for IE?
        Response.Cache.SetCacheability(HttpCacheability.NoCache);

        // Is this required for FireFox? Would be good to do this without magic strings.
        // Won't it overwrite the previous setting
        Response.Headers.Add("Cache-Control", "no-cache, no-store");

        // Why is it necessary to explicitly call SetExpires. Presume it is still better than calling
        // Response.Headers.Add( directly
        Response.Cache.SetExpires(DateTime.UtcNow.AddYears(-1));
    }
}
Martin Hollingsworth
  • 7,249
  • 7
  • 49
  • 51
  • 5
    I would attempt to answer if I didn't know how horribly impossible thy task is. Controlling the client's cache is like trying to use 10 foot long chopsticks to rearrange furniture. – Jeff Meatball Yang May 27 '09 at 06:03
  • A whole lot of answers that cover just a part of the problem would still be very valuable. Please throw in your 2 cents worth. – Martin Hollingsworth May 27 '09 at 06:22

6 Answers6

100

This is what we use in ASP.NET:

// Stop Caching in IE
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

// Stop Caching in Firefox
Response.Cache.SetNoStore();

It stops caching in Firefox and IE, but we haven't tried other browsers. The following response headers are added by these statements:

Cache-Control: no-cache, no-store
Pragma: no-cache
HttpWatchSupport
  • 2,804
  • 1
  • 17
  • 16
  • 5
    +1 This is working for me in Chrome, thanks a lot. I also use Response.Cache.SetAllowResponseInBrowserHistory(true); to avoid history to store an entry for each request of the same page. – daniloquio Mar 06 '12 at 19:11
  • 12
    Apparently someone has discovered that using SetCacheability with NoCache also disables the ASP.NET output cache (server-side cache). They suggest to use the ServerAndNoCache option instead. http://codeclimber.net.nz/archive/2007/04/01/Beware-the-ASP.NET-SetCacheability-method.aspx – md1337 Mar 07 '12 at 21:22
  • 1
    To clarify the comments in the code snippet, the main method is `SetCacheability`. `SetNoStore` is an IE6 workaround. See [Why both no-cache and no-store should be used in HTTP response?](http://stackoverflow.com/q/866822/145173). – Edward Brey Mar 28 '13 at 01:12
  • 3
    FWIW ... Needed to add SetNoStore for IE10 – felickz May 09 '13 at 20:26
  • For those reading this page who will be outputting dynamic PDFs over https and setting the cache headers like this, please beware the following IE8 and lower bug: http://stackoverflow.com/questions/1038707/cant-display-pdf-from-https-in-ie-8-on-64-bit-vista – Paddy Sep 17 '14 at 10:26
  • This is the absolute right question on this topic! I have tried everything, action fiters onExecuting and onExecuted with all kind of combinations and nothing workes. But adding this on my rendering model worked like a charm! – Alexander Nov 24 '20 at 15:34
42

For what it's worth, I just had to handle this in my ASP.NET MVC 3 application. Here is the code block I used in the Global.asax file to handle this for all requests.

    protected void Application_BeginRequest()
    {
        //NOTE: Stopping IE from being a caching whore
        HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false);
        HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        HttpContext.Current.Response.Cache.SetNoStore();
        Response.Cache.SetExpires(DateTime.Now);
        Response.Cache.SetValidUntilExpires(true);
    }
Adam Carr
  • 2,986
  • 7
  • 31
  • 38
  • The `HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false)` made the difference to prevent caching in bith IE and FireFox – Michael Kniskern Jun 07 '11 at 22:43
  • 2
    -1, setting in these Application_BeginRequest() causes the no-cache headers to be sent for items that you'll probably want cached (JavaScript files, images, etc). I haven't tried it yet, but the OP's location (setting the headers in the ASP page itself) is probably better. – Evan Haas Aug 05 '13 at 17:00
  • I did expect this answer to work as it is neatest way to set it in glabal.asax but no joy yet – Laurence Aug 06 '13 at 14:17
  • 5
    @Evan, Application_BeginRequest will only be called for requests that are sent from IIS to ASP.NET. Many times, static files like CSS, JS, Images, Fonts, etc. are extensions that are considered static files from IIS and not sent to the ASP.NET Runtime. If IIS is set up to send all requests to the ASP.NET runtime, then yes, this would apply to all requests, even if the files are static and should be cached. – Adam Carr Dec 08 '13 at 07:48
  • @Adam, makes sense. I would undo my -1 but SO says my vote is locked in :-( – Evan Haas Dec 11 '13 at 15:11
  • OK, nit pick here... The `HttpResponse` object is being referenced 2 different ways: 1) `HttpContext.Current.Response` and 2) `Response`. It would probably be cleaner to pick one or the other. – dana Apr 23 '14 at 16:17
  • I've found applying a global action filter to be more modular. Plus you can accommodate situations where MVC is serving up static files (like Bundled scripts and styles). http://stackoverflow.com/a/23682242/120955 – StriplingWarrior May 15 '14 at 15:26
  • StriplingWarrior is right, this method also appears to affect bundles (which is not what most people would want). In local environment it will also affect static files like Evan Haas said, but on remote server, IIS will handle those (unless you set it differently for some reason). I've patched up a quick and dirty solution to this problem here http://stackoverflow.com/a/23695387/2123652 – jahu May 16 '14 at 12:50
2

I've tried various combinations and had them fail in FireFox. It has been a while so the answer above may work fine or I may have missed something.

What has always worked for me is to add the following to the head of each page, or the template (Master Page in .net).

<script language="javascript" type="text/javascript">
    window.onbeforeunload = function () {   
        // This function does nothing.  It won't spawn a confirmation dialog   
        // But it will ensure that the page is not cached by the browser.
    }  
</script>

This has disabled all caching in all browsers for me without fail.

Steve
  • 121
  • 1
  • 2
  • 7
    Not sure what this is supposed to do, but it does look like a big fat hack that is bound to fail in the next update of any of these browsers. – md1337 Mar 07 '12 at 21:10
  • It's explained at e.g. https://web.archive.org/web/20160112095216/http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript -- in summary the onbeforeunload event was implemented to be used by banks and prevents the page being cached. – ChrisW Nov 05 '16 at 07:48
1

There are two approaches that I know of. The first is to tell the browser not to cache the page. Setting the Response to no cache takes care of that, however as you suspect the browser will often ignore this directive. The other approach is to set the date time of your response to a point in the future. I believe all browsers will correct this to the current time when they add the page to the cache, but it will show the page as newer when the comparison is made. I believe there may be some cases where a comparison is not made. I am not sure of the details and they change with each new browser release. Final note I have had better luck with pages that "refresh" themselves (another response directive). The refresh seems less likely to come from the cache.

Hope that helps.

Pat O
  • 1,344
  • 3
  • 12
  • 27
0

I'm going to test adding the no-store tag to our site to see if this makes a difference to browser caching (Chrome has sometimes been caching the pages). I also found this article very useful on documentation on how and why caching works and will look at ETag's next if the no-store is not reliable:

http://www.mnot.net/cache_docs/

http://en.wikipedia.org/wiki/HTTP_ETag

The Coder
  • 4,981
  • 2
  • 29
  • 36
0

See also How to prevent google chrome from caching my inputs, esp hidden ones when user click back? without which Chrome might reload but preserve the previous content of <input> elements -- in other words, use autocomplete="off".

Community
  • 1
  • 1
ChrisW
  • 54,973
  • 13
  • 116
  • 224