Disable browser cache for entire ASP.NET website

I am looking for a method to disable the browser cache for an entire ASP.NET MVC Website

I found the following method:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.Cache.SetNoStore();

And also a meta tag method (it won't work for me, since some MVC actions send partial HTML/JSON through Ajax, without a head, meta tag).

<meta http-equiv="PRAGMA" content="NO-CACHE">

But I am looking for a simple method to disable the browser cache for an entire website.


Solution 1:

Create a class that inherits from IActionFilter.

public class NoCacheAttribute : ActionFilterAttribute
{  
    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);
    }
}

Then put attributes where needed...

[NoCache]
[HandleError]
public class AccountController : Controller
{
    [NoCache]
    [Authorize]
    public ActionResult ChangePassword()
    {
        return View();
    }
}

Solution 2:

Instead of rolling your own, simply use what's provided for you.

As mentioned previously, do not disable caching for everything. For instance, jQuery scripts used heavily in ASP.NET MVC should be cached. Actually ideally you should be using a CDN for those anyway, but my point is some content should be cached.

What I find works best here rather than sprinkling the [OutputCache] everywhere is to use a class:

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class NoCacheController  : Controller
{
}

All of your controllers you want to disable caching for then inherit from this controller.

If you need to override the defaults in the NoCacheController class, simply specify the cache settings on your action method and the settings on your Action method will take precedence.

[HttpGet]
[OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
public ViewResult Index()
{
  ...
}

Solution 3:

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();

All requests get routed through default.aspx first - so assuming you can just pop in code behind there.

Solution 4:

You may want to disable browser caching for all pages rendered by controllers (i.e. HTML pages), but keep caching in place for resources such as scripts, style sheets, and images. If you're using MVC4+ bundling and minification, you'll want to keep the default cache durations for scripts and stylesheets (very long durations, since the cache gets invalidated based on a change to a unique URL, not based on time).

In MVC4+, to disable browser caching across all controllers, but retain it for anything not served by a controller, add this to FilterConfig.RegisterGlobalFilters:

filters.Add(new DisableCache());

Define DisableCache as follows:

class DisableCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}