我有一个ASP.NET MVC 3应用程序。该应用程序通过jQuery请求记录。jQuery回调到控制器操作,该操作以JSON格式返回结果。我无法证明这一点,但是我担心我的数据可能会被缓存。
我只希望将缓存应用于特定的操作,而不是应用于所有操作。
是否可以执行一项操作以确保不缓存数据的属性?如果没有,如何确保浏览器每次都获得一组新的记录,而不是一组缓存的记录?
我有一个ASP.NET MVC 3应用程序。该应用程序通过jQuery请求记录。jQuery回调到控制器操作,该操作以JSON格式返回结果。我无法证明这一点,但是我担心我的数据可能会被缓存。
我只希望将缓存应用于特定的操作,而不是应用于所有操作。
是否可以执行一项操作以确保不缓存数据的属性?如果没有,如何确保浏览器每次都获得一组新的记录,而不是一组缓存的记录?
Answers:
为了确保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 Framework: [OutputCache(NoStore = true, Duration = 0)]
对于.net Core: [ResponseCache(NoStore = true, Duration = 0)]
请注意,不可能强制浏览器禁用缓存。您能做的最好的事情就是提供大多数浏览器都会推荐的建议,通常是标题或元标记的形式。此decorator属性将禁用服务器缓存,并添加以下标头:Cache-Control: public, no-store, max-age=0
。它不添加元标记。如果需要,可以将其手动添加到视图中。
另外,JQuery和其他客户端框架将尝试通过向URL中添加内容(例如时间戳或GUID)来欺骗浏览器以不使用其资源的缓存版本。这可以有效地使浏览器再次请求资源,但实际上并不能阻止缓存。
最后一点。您应该意识到,资源也可以缓存在服务器和客户端之间。ISP,代理和其他网络设备也缓存资源,并且它们通常使用内部规则而不查看实际资源。您无能为力。好消息是,它们通常缓存较短的时间范围,例如秒或分钟。
Cache-Control:public, no-store, max-age=0
。它不添加元标记。如果需要,可以将其手动添加到视图中。
NoStore = true
and Duration = 0
(我已经成功使用了,谢谢),但是VaryByParam = "None"
其他两个选项会影响所有请求,而与参数无关,还会有什么其他效果?
所有你需要的是:
[OutputCache(Duration=0)]
public JsonResult MyAction(
或者,如果您想为整个控制器禁用它:
[OutputCache(Duration=0)]
public class MyController
尽管此处有评论争论,但这足以禁用浏览器缓存-这导致ASP.Net发出响应头,告知浏览器文档立即过期:
Cache-Control
为public
max-age=0
从不意味着“禁用缓存”。这仅意味着将响应内容视为立即过期,但是允许使用缓存对其进行缓存。浏览器应在使用之前验证缓存的过时内容的新鲜度,但这不是强制性的,除非must-revalidate
指定了其他指令。
这是NoCache
mattytommo提出的属性,通过使用Chris Moschini的答案中的信息进行了简化:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : OutputCacheAttribute
{
public NoCacheAttribute()
{
this.Duration = 0;
}
}
max-age=0
从不意味着“禁用缓存”。这仅意味着将响应内容视为立即过期,但是允许使用缓存对其进行缓存。浏览器应在使用之前验证缓存的过时内容的新鲜度,但这不是强制性的,除非must-revalidate
指定了其他指令。
no-cache
,该指令仍允许缓存,但必须在使用前在原始服务器上重新验证。为了避免甚至重新验证缓存,你必须添加no-store
一起no-cache
。(no-store
仅是错误的做法,因为易失性缓存允许缓存标记为的内容no-store
。)
对于MVC6(DNX),没有System.Web.OutputCacheAttribute
注意:设置NoStore
持续时间参数时不考虑。可以设置首次注册的初始时长,并使用自定义属性覆盖此初始时长。
但是我们有 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());
}
为了防止浏览器缓存(包括Internet Explorer 11),Asp.Net MVC Core的正确属性值为:
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
如Microsoft文档中所述:
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 = "*")]