我正在尝试确保某个页面永远不会被缓存,并且在用户单击后退按钮时从不显示。 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,所以它看起来是服务器问题,而不是与浏览器相关的问题。答案 0 :(得分:36)
通过反复试验,我发现在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缓存控制问题是:
答案 1 :(得分:0)
我想在JK的答案中添加一些内容:
如果将缓存控件的限制值设置为比现有限制更严格,则可以。 (即:在不公开时设置为非缓存)
但是,如果您希望设置的限制值小于已经达到的限制(即:设置为private(当它是非缓存时)),则以下代码将不起作用:>
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,
};
}
}
答案 2 :(得分: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用于其他标头。例如,在诸如包(jquery,bootstrap)之类的静态内容上。寻找这些部分customheader,staticcontent。