覆盖 ASP.NET 缓存策略并将 Cache-Control 设置为 public
Override ASP.NET cache policy and set Cache-Control to public
我想在我的 ASP.NET (MVC) 应用程序中将 Cache-Control
header 设置为 public
。问题是有代码(我无法更改)之前设置缓存策略是这样的:
var response = htmlHelper.ViewContext.HttpContext.Response;
response.Cache.SetExpires(System.DateTime.UtcNow.AddDays(-1));
response.Cache.SetValidUntilExpires(false);
response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
response.Cache.SetCacheability(HttpCacheability.NoCache);
response.Cache.SetNoStore();
我以后找不到覆盖它的方法,因为无论我如何尝试设置缓存控制,上面的都会生效。例如。以下都不能对抗之前被禁用的缓存:
httpContext.Response.Headers["Cache-Control"] = "public";
var cache = httpContext.Response.Cache;
cache.SetExpires(cacheItem.ValidUntilUtc);
cache.SetValidUntilExpires(true);
cache.SetRevalidation(HttpCacheRevalidation.None);
cache.SetCacheability(HttpCacheability.Public);
cache.SetMaxAge(cacheItem.ValidUntilUtc - _clock.UtcNow);
有没有办法以某种方式覆盖或重置缓存策略?
在您的第一个代码示例中,缓存属性似乎是在 HTML 帮助程序中设置的,它很可能以某种方式呈现在视图上。我猜你试图覆盖属性发生得太早,然后在视图的渲染中被覆盖。
显然,更改设置这些 headers 的代码是最好的。如果你绝对不能,我看到了一些前进的路线:
不要return 立即从控制器查看。你可能有这样的东西:
public ActionResult MyAction() {
// code here
return View();
}
将其转换为这样您就可以尝试覆盖视图中的缓存:
public ActionResult MyAction() {
// code here
var result = View();
ResetCaching();
return result;
}
如果这不起作用,请在控制器中使用 OnResultExecuted
或 OnActionExecuted
来捕获视图何时已完成执行或操作已执行并尝试覆盖在执行视图 and/or 操作之后但在处理控制器之前进行缓存。
您可以实现一个 custom action filter,而不是覆盖控制器上的实际事件,这可以使代码更简洁并允许您在多个地方重用它。
绝对最差情况,使用global.asax
文件中的Application_PreSendRequestHeaders
事件,如果请求满足缓存重置的要求,修改headers就在它们被发送到浏览器之前。此方法将使您检查通过您的应用程序的每个请求。
显然这不可能,因为 HttpCachePolicy
会主动阻止您设置 "higher" 可缓存性,即如果您在设置 NoCache 后尝试设置 Public,什么都不会发生了。
似乎唯一的、hackish 的方法是使用私有反射并调用内部 Reset
方法,如下所示:
var cache = httpContext.Response.Cache;
var cachePolicy = (HttpCachePolicy)typeof(HttpCachePolicyWrapper).InvokeMember("_httpCachePolicy", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, cache, null);
typeof(HttpCachePolicy).InvokeMember("Reset", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, cachePolicy, null);
cache.SetCacheability(HttpCacheability.Public);
我想在我的 ASP.NET (MVC) 应用程序中将 Cache-Control
header 设置为 public
。问题是有代码(我无法更改)之前设置缓存策略是这样的:
var response = htmlHelper.ViewContext.HttpContext.Response;
response.Cache.SetExpires(System.DateTime.UtcNow.AddDays(-1));
response.Cache.SetValidUntilExpires(false);
response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
response.Cache.SetCacheability(HttpCacheability.NoCache);
response.Cache.SetNoStore();
我以后找不到覆盖它的方法,因为无论我如何尝试设置缓存控制,上面的都会生效。例如。以下都不能对抗之前被禁用的缓存:
httpContext.Response.Headers["Cache-Control"] = "public";
var cache = httpContext.Response.Cache;
cache.SetExpires(cacheItem.ValidUntilUtc);
cache.SetValidUntilExpires(true);
cache.SetRevalidation(HttpCacheRevalidation.None);
cache.SetCacheability(HttpCacheability.Public);
cache.SetMaxAge(cacheItem.ValidUntilUtc - _clock.UtcNow);
有没有办法以某种方式覆盖或重置缓存策略?
在您的第一个代码示例中,缓存属性似乎是在 HTML 帮助程序中设置的,它很可能以某种方式呈现在视图上。我猜你试图覆盖属性发生得太早,然后在视图的渲染中被覆盖。
显然,更改设置这些 headers 的代码是最好的。如果你绝对不能,我看到了一些前进的路线:
不要return 立即从控制器查看。你可能有这样的东西:
public ActionResult MyAction() { // code here return View(); }
将其转换为这样您就可以尝试覆盖视图中的缓存:
public ActionResult MyAction() { // code here var result = View(); ResetCaching(); return result; }
如果这不起作用,请在控制器中使用
OnResultExecuted
或OnActionExecuted
来捕获视图何时已完成执行或操作已执行并尝试覆盖在执行视图 and/or 操作之后但在处理控制器之前进行缓存。
您可以实现一个 custom action filter,而不是覆盖控制器上的实际事件,这可以使代码更简洁并允许您在多个地方重用它。绝对最差情况,使用
global.asax
文件中的Application_PreSendRequestHeaders
事件,如果请求满足缓存重置的要求,修改headers就在它们被发送到浏览器之前。此方法将使您检查通过您的应用程序的每个请求。
显然这不可能,因为 HttpCachePolicy
会主动阻止您设置 "higher" 可缓存性,即如果您在设置 NoCache 后尝试设置 Public,什么都不会发生了。
似乎唯一的、hackish 的方法是使用私有反射并调用内部 Reset
方法,如下所示:
var cache = httpContext.Response.Cache;
var cachePolicy = (HttpCachePolicy)typeof(HttpCachePolicyWrapper).InvokeMember("_httpCachePolicy", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, cache, null);
typeof(HttpCachePolicy).InvokeMember("Reset", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, cachePolicy, null);
cache.SetCacheability(HttpCacheability.Public);