我试图确保某个页面永远不会被缓存,并且在用户单击后退按钮时从不显示。 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,所以它看起来是一个服务器问题,而不是浏览器相关的问题。
通过反复试验,我发现在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缓存控制问题是:
我想在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,
};
}
}
如果您在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。