75

How to disable automatic browser caching from asp.Net mvc application?

Because I am having a problem with caching as it caches all links. But sometimes it redirected to DEFAULT INDEX PAGE automatically which stored it caching and then all the time I click to that link it will redirect me to DEFAULT INDEX PAGE.

So some one know how to manually disable caching option from ASP.NET MVC 4?

Reddy
  • 8,737
  • 11
  • 55
  • 73
Raj Tamakuwala
  • 1,163
  • 1
  • 9
  • 18

6 Answers6

143

You can use the OutputCacheAttribute to control server and/or browser caching for specific actions or all actions in a controller.

Disable for all actions in a controller

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)] // will be applied to all actions in MyController, unless those actions override with their own decoration
public class MyController : Controller
{
  // ... 
}

Disable for a specific action:

public class MyController : Controller
{
    [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)] // will disable caching for Index only
    public ActionResult Index()
    {
       return View();
    }
} 

If you want to apply a default caching strategy to all actions in all controllers, you can add a global action filter by editing your global.asax.cs and looking for the RegisterGlobalFilters method. This method is added in the default MVC application project template.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new OutputCacheAttribute
                    {
                        VaryByParam = "*",
                        Duration = 0,
                        NoStore = true,
                    });
    // the rest of your global filters here
}

This will cause it to apply the OutputCacheAttribute specified above to every action, which will disable server and browser caching. You should still be able to override this no-cache by adding OutputCacheAttribute to specific actions and controllers.

moribvndvs
  • 42,191
  • 11
  • 135
  • 149
  • thanks let me check its great to do this for particular controller only – Raj Tamakuwala Oct 18 '12 at 06:31
  • Ah, yeah, I thought you meant you wanted it on every controller in your application. I'll update my answer to cover both. – moribvndvs Oct 18 '12 at 06:33
  • look like data is still being cached, i just clear all caching and add your code to global.asax. and check the caching but its still adding the cache. look like its not working for me. can u tell wt can be problem ? – Raj Tamakuwala Oct 18 '12 at 06:39
  • Hmm, there shouldn't be anything else to it. I used all three of these techniques often and they don't give me any trouble. I'd check to make sure the issue is actually with caching. One thing you can do is verify the cache directives by checking the response headers with a tool such as Fiddler. – moribvndvs Oct 18 '12 at 06:47
  • Worked fine for me to control browser cache when applied to a method directly. I didn't add it as a filter though. – Andrew Dec 30 '13 at 05:50
  • 2
    I thought it worked, but then I started getting Duration must be a positive number in my controller. – Loganj99 Jun 06 '14 at 16:34
  • @Loganj99 Are you using MVC 5? That may be something that has been changed since 4 and when my answer was posted. – moribvndvs Jun 06 '14 at 16:55
  • @HackedByChinese No it is MVC 3. – Loganj99 Jun 09 '14 at 14:53
  • Thanks..I added previously on global.asax and the functionality is working eventhough images are not loading.But this fixed the issue. – Ramesh Dec 15 '14 at 06:15
  • [From MSDN](https://msdn.microsoft.com/en-us/library/system.web.mvc.outputcacheattribute(v=vs.118).aspx) "Output caching lets you store the output of an action method in memory on the Web server." That doesn't seem to include client-side caching. Why would this do anything on the client side? – Joep Beusenberg Jul 21 '15 at 07:38
  • 2
    That can't be used with ChildActions – T-moty Apr 28 '16 at 13:34
  • 1
    For anyone looking in their code for the `RegisterGlobalFilters` method, it sometimes exists in `App_Start\FilterConfig.cs` rather than in `Global.asax.cs`. – Tawab Wakil Aug 07 '19 at 18:59
  • What does VaryByParam do ? – love2code Oct 11 '19 at 21:07
  • Is this safe for personalised pages? Even with Duration 0 & NoStore options, I think I've seen an example of personalised information being shown for a different user. – ProNotion Dec 19 '19 at 16:56
28

HackedByChinese is missing the point. He mistook server cache with client cache. OutputCacheAttribute controls server cache (IIS http.sys cache), not browsers (clients) cache.

I give you a very small part of my codebase. Use it wisely.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class NoCacheAttribute : FilterAttribute, IResultFilter
{
    public void OnResultExecuting(ResultExecutingContext filterContext)
    {
    }

    public void OnResultExecuted(ResultExecutedContext filterContext)
    {
        var cache = filterContext.HttpContext.Response.Cache;
        cache.SetCacheability(HttpCacheability.NoCache);
        cache.SetRevalidation(HttpCacheRevalidation.ProxyCaches);
        cache.SetExpires(DateTime.Now.AddYears(-5));
        cache.AppendCacheExtension("private");
        cache.AppendCacheExtension("no-cache=Set-Cookie");
        cache.SetProxyMaxAge(TimeSpan.Zero);
    }
}

Usage:

/// will be applied to all actions in MyController
[NoCache]
public class MyController : Controller
{
    // ... 
}

Use it wisely as it really disables all client cache. The only cache not disabled is the "back button" browser cache. But is seems there is really no way to get around it. Maybe only by using javascript to detect it and force page or page zones refresh.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Softlion
  • 12,281
  • 11
  • 58
  • 88
  • This anti caching feature Works perfectly on a commercial web site for More than 3 years. Use fiddler to check the cache headers in the http response. – Softlion Oct 19 '12 at 06:23
  • 12
    I understood the point. When using OutputCacheAttribute and setting NoStore=true, browser cache is forbidden (the response headers will look something like `Cache-Control: public, no-store, max-age=0 Expires: Mon, 22 Oct 2012 20:19:26 GMT Last-Modified: Mon, 22 Oct 2012 20:19:26 GMT`). Therefore, it will prevent server AND browser cache. I know it's curious that it sets `public` in addition to no-store, but the net effect is no-store and immediate expiration. – moribvndvs Oct 22 '12 at 20:24
  • you mean it will not cache as immediate expiration will take place ? – Raj Tamakuwala Oct 23 '12 at 06:11
  • It does not work for me either. Browser caching is still happening. – Obi Wan Oct 15 '13 at 13:38
  • It works perfectly. You have to verify using fiddle where the caching occurs. Always CTRL-F5 2 times between 2 tests, and also reset IIS. It will not work for a child action having [OutputCache] attribute set. – Softlion Oct 15 '13 at 16:06
  • 1
    This also worked for me, with or without SetNoStore(). @HackedByChinese built in filter results in `Cache-Control: public, no-cache="Set-Cookie", no-store, max-age=0` & `Expires` + `Vary` set. This solution results in `Cache-Control: no-cache, proxy-revalidate, private, no-cache=Set-Cookie`, `Expires=-1` and `Pragma=no-cache`. Since they both work just fine in controlling browser caches, not sure what the issue is. – Andrew Dec 30 '13 at 05:52
  • @HackedByChinese I think the problem with Expires set to DateTime.Now is clock drift between the client and server. Suppose my requests are coming from a scrolling event in the UI, and the user is scrolling very fast, so there are a lot of events. Therefore, Softlion has a better solution in subtracting 5 years. Point being, yours will ONLY guarantee server cache expiration, AND MAY clear the browser cache but ALSO have hard-to-reproduce conditions where browser cache sticks around. – John Zabroski Jan 02 '14 at 20:24
  • It works great and now I know how to do my own attribute filters. I could see in the debugger that when I changed the ID in the get request from a $.getJSON call where data was previously loaded, the controller method never got called. Your custom NoCache cleanly fixed the problem. – Dan Randolph Jul 20 '15 at 00:37
14

We can set cache profile in the Web.config file instead of setting cache values individually in pages to avoid redundant code. We can refer the profile by using the CacheProfile property of the OutputCache attribute. This cache profile will be applied to all pages unless the page/method overrides these settings.

<system.web>
  <caching>
    <outputCacheSettings>
      <outputCacheProfiles>
        <add name="CacheProfile" duration="60" varyByParam="*" />
      </outputCacheProfiles>
    </outputCacheSettings>
  </caching>
</system.web>

And if you want to disable the caching from your particular action or controller, you can override the config cache settings by decorating that specific action method like shown below:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult NoCachingRequired()
{
    return PartialView("abcd");
}

Hope this is clear and is useful to you.

Swati Gupta
  • 546
  • 3
  • 8
9

If you want to prevent browser caching, you can use this code from ShareFunction

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
}
Jeff Lequeux
  • 276
  • 4
  • 5
5

For on page solution ,Set this in your layout page :

<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
Pranav Labhe
  • 1,943
  • 1
  • 19
  • 24
0

To make my answer visible to all, I move my comment to answer for this question.

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">

This will work in all browsers (IE, Firefox and Chrome as well). Happy to hear my answer worked for you @Joseph Katzman

Kannan_PK
  • 99
  • 6