缓存控制:无存储,必须重新验证未发送到IIS7 + ASP.NET MVC中的客户端浏览器

问题描述 投票:23回答:3

我试图确保某个页面永远不会被缓存,并且在用户单击后退按钮时从不显示。 This very highly rated answer (currently 1068 upvotes) says to use

Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");

但是在IIS7 / ASP.NET MVC中,当我发送这些头时,客户端会看到这些响应头:

Cache-control: private, s-maxage=0 // that's not what I set them to
Pragma: no-cache
Expires: 0

缓存控制头怎么了? IIS7或ASP.NET本机的内容是否会覆盖它?我检查了我的解决方案,我没有覆盖此标头的代码。

当我首先添加Response.Headers.Remove("Cache-Control");时,它没有任何区别:

Response.Headers.Remove("Cache-Control");
Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");

当我添加[OutputCache]属性时:

[OutputCache(Location = OutputCacheLocation.None)]
public ActionResult DoSomething()
{
   Response.Headers.Remove("Cache-Control");
   Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
   Response.AppendHeader("Pragma", "no-cache");
   Response.AppendHeader("Expires", "0");

   var model = DoSomething();
   return View(model);
}

然后客户端响应标头更改为:

Cache-control: no-cache
Pragma: no-cache
Expires: 0

哪个更接近,但仍然不是我要发送的标题。这些标题在哪里被覆盖,我该如何阻止它?

编辑:我已经检查过,错误的标题被发送到Chrome,FF,IE和Safari,所以它看起来是一个服务器问题,而不是浏览器相关的问题。

c# asp.net-mvc iis-7 http-headers cache-control
3个回答
42
投票

通过反复试验,我发现在ASP.NET MVC中为IIS7正确设置标头的一种方法是:

Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");

第一行将Cache-control设置为no-cache,第二行添加其他属性no-store, must-revalidate

这可能不是唯一的方法,但如果更简单的Response.AppendHeader("Cache-control", "no-cache, no-store, must-revalidate");失败,它确实提供了另一种方法。

可能由此解决的其他相关IIS7缓存控制问题是:


0
投票

我想在JK的答案中添加一些内容: 如果您将缓存控制设置为比现有值更严格的值,则可以。 (即:设置no-cache,当它是私有的时)

但是,如果你想设置一个比现在更少限制的值(即:设置为private,当它是no-cache时),下面的代码将不起作用:

Response.Cache.SetCacheability(HttpCacheability.Private);

因为,SetCacheablitiy方法在下面有此代码,并且只有在限制性更强时才设置缓存标志:

if (s_cacheabilityValues[(int)cacheability] < s_cacheabilityValues[(int)_cacheability]) {
    Dirtied();
   _cacheability = cacheability;
}

要在.net mvc中克服此问题,您需要获取HttpResponseMessage的实例并将CacheControlHeaderValue分配给其Headers.CacheControl值:

actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue
                                   {
                                       MaxAge = TimeSpan.FromSeconds(3600),
                                       Private = true
                                   };

动作过滤器中提供了HttpResponseMessage的一个实例。您可以编写一个动作过滤器来设置缓存标头值,如下所示:

public class ClientSideCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var response = actionExecutedContext.ActionContext.Response;
        response.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue
        {
            MaxAge = TimeSpan.FromSeconds(9999),
            Private = true,
        };
    }
}

0
投票

如果您在MVC应用程序中全局需要这些标头。添加此课程。

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class CustomHeaders : System.Web.Mvc.ActionFilterAttribute
{
    [OutputCache(Location = System.Web.UI.OutputCacheLocation.None)]
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.RequestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.RequestContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
        context.RequestContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
        context.RequestContext.HttpContext.Response.AppendHeader("Expires", "0");

        base.OnActionExecuted(context);
    }
}

对于全局使用,请将其添加到FilterConfig。

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new CustomHeaders());
    }
}

或者只在特定控制器上使用这些标头。

[Authorize]
[CustomHeaders]
public class HomeController : Controller
{
    [AllowAnonymous]
    public ActionResult Index()

附注:您可以将IIS和web.config用于其他标头。例如关于像bundle这样的静态内容(jquery,bootstrap)。查找这些部分customheaders,staticcontent。

© www.soinside.com 2019 - 2024. All rights reserved.