我有一个 ASP.NET MVC 3 应用程序。该应用程序通过 jQuery 请求记录。 jQuery 回调控制器操作,以 JSON 格式返回结果。我无法证明这一点,但我担心我的数据可能会被缓存。
我只想将缓存应用于特定操作,而不是所有操作。
我可以在操作上添加一个属性来确保数据不会被缓存吗?如果不是,如何确保浏览器每次获取一组新记录,而不是缓存的记录集?
为了确保 JQuery 不会缓存结果,请在您的 ajax 方法上添加以下内容:
$.ajax({
cache: false
//rest of your ajax setup
});
或者为了防止 MVC 中的缓存,我们创建了自己的属性,您也可以这样做。这是我们的代码:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed 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);
}
}
然后用
[NoCache]
装饰你的控制器。或者,要为所有用户执行此操作,您只需将该属性放在您继承控制器的基类的类上(如果您有的话),就像我们在这里一样:
[NoCache]
public class ControllerBase : Controller, IControllerBase
如果您需要某些操作不可缓存,您还可以使用此属性来装饰它们,而不是装饰整个控制器。
如果您的类或操作在浏览器中呈现时没有
NoCache
并且您想检查它是否正常工作,请记住,在编译更改后,您需要在您的浏览器中执行“硬刷新”(Ctrl+F5)浏览器。在此之前,您的浏览器将保留旧的缓存版本,并且不会使用“正常刷新”(F5) 来刷新它。
您可以使用内置的缓存属性来防止缓存。
对于 .NET 框架:
[OutputCache(NoStore = true, Duration = 0)]
对于 .NET Core:
[ResponseCache(NoStore = true, Duration = 0)]
请注意,不可能强制浏览器禁用缓存。您能做的最好的事情就是提供大多数浏览器都会接受的建议,通常以标头或元标记的形式。此装饰器属性将禁用服务器缓存并添加此标头:
Cache-Control: public, no-store, max-age=0
。它不添加元标记。如果需要,可以在视图中手动添加这些内容。
此外,jQuery 和其他客户端框架将尝试通过向 url 添加内容(例如时间戳或 GUID)来欺骗浏览器不使用其资源的缓存版本。这可以有效地让浏览器再次请求资源,但并不能真正阻止缓存。
最后一点。您应该知道资源也可以缓存在服务器和客户端之间。 ISP、代理和其他网络设备也会缓存资源,并且它们通常使用内部规则而不查看实际资源。对于这些你无能为力。好消息是,它们通常会缓存较短的时间范围,例如几秒或几分钟。
您所需要的是:
[OutputCache(Duration=0)]
public JsonResult MyAction(
或者,如果您想为整个控制器禁用它:
[OutputCache(Duration=0)]
public class MyController
尽管这里的评论存在争议,但这足以禁用浏览器缓存 - 这会导致 ASP.Net 发出响应标头,告诉浏览器文档立即过期:
在控制器操作中将以下行附加到标题中
public ActionResult Create(string PositionID)
{
Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.
这是 mattytommo 提出的
NoCache
属性,通过使用 Chris Moschini 的答案中的信息进行了简化:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : OutputCacheAttribute
{
public NoCacheAttribute()
{
this.Duration = 0;
}
}
对于MVC6(DNX),没有
System.Web.OutputCacheAttribute
注意:当您设置
NoStore
时,不考虑 Duration 参数。可以设置首次注册的初始持续时间并使用自定义属性覆盖它。
但是我们有
Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter
public void ConfigureServices(IServiceCollection services)
...
services.AddMvc(config=>
{
config.Filters.Add(
new ResponseCacheFilter(
new CacheProfile() {
NoStore=true
}));
}
...
)
可以使用自定义属性覆盖初始过滤器
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
var filter=filterContext.Filters.Where(t => t.GetType() == typeof(ResponseCacheFilter)).FirstOrDefault();
if (filter != null)
{
ResponseCacheFilter f = (ResponseCacheFilter)filter;
f.NoStore = true;
//f.Duration = 0;
}
base.OnResultExecuting(filterContext);
}
}
这是一个用例
[NoCache]
[HttpGet]
public JsonResult Get()
{
return Json(new DateTime());
}
ASP.NET MVC 5 解决方案:
App_Start/FilterConfig.cs
的RegisterGlobalFilters
方法: public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// ...
filters.Add(new OutputCacheAttribute
{
NoStore = true,
Duration = 0,
VaryByParam = "*",
Location = System.Web.UI.OutputCacheLocation.None
});
}
}
OutputCache
或 Controller
级别应用不同的 View
指令来覆盖全局过滤器。对于常规控制器来说是[OutputCache(NoStore = true, Duration = 0, Location=System.Web.UI.ResponseCacheLocation.None, VaryByParam = "*")]
或者如果它是
ApiController
那就是
[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, Location = System.Web.UI.OutputCacheLocation.None, VaryByParam = "*")]
防止浏览器缓存(包括 Internet Explorer 11)的 Asp.Net MVC Core 的正确属性值为:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
如 Microsoft 文档中所述:
MVC 中的输出缓存
[OutputCache(NoStore = true,持续时间= 0,位置=“无”,VaryByParam =“*”)] 或者 [OutputCache(NoStore = true,持续时间 = 0,VaryByParam = "无")]