C# 使用属性防止在 ASP.NET MVC 中缓存特定操作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10011780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:08:01  来源:igfitidea点击:

Prevent Caching in ASP.NET MVC for specific actions using an attribute

c#jquery.netasp.net-mvcasp.net-mvc-3

提问by JavaScript Developer

I have an ASP.NET MVC 3 application. This application requests records through jQuery. jQuery calls back to a controller action that returns results in JSON format. I have not been able to prove this, but I'm concerned that my data may be getting cached.

我有一个 ASP.NET MVC 3 应用程序。此应用程序通过 jQuery 请求记录。jQuery 回调以 JSON 格式返回结果的控制器操作。我无法证明这一点,但我担心我的数据可能会被缓存。

I only want the caching to be applied to specific actions, not for all actions.

我只希望缓存应用于特定操作,而不是所有操作。

Is there an attribute that I can put on an action to ensure that the data does not get cached? If not, how do I ensure that the browser gets a new set of records each time, instead of a cached set?

是否有一个属性可以用来确保数据不会被缓存?如果没有,我如何确保浏览器每次都获得一组新记录,而不是缓存集?

采纳答案by mattytommo

To ensure that JQuery isn't caching the results, on your ajax methods, put the following:

为确保 JQuery 不缓存结果,请在您的 ajax 方法中添加以下内容:

$.ajax({
    cache: false
    //rest of your ajax setup
});

Or to prevent caching in MVC, we created our own attribute, you could do the same. Here's our code:

或者为了防止 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);
    }
}

Then just decorate your controller with [NoCache]. OR to do it for all you could just put the attribute on the class of the base class that you inherit your controllers from (if you have one) like we have here:

然后只需用[NoCache]. 或者要做到这一点,您只需将属性放在您继承控制器的基类的类上(如果您有控制器),就像我们在这里一样:

[NoCache]
public class ControllerBase : Controller, IControllerBase

You can also decorate some of the actions with this attribute if you need them to be non-cacheable, instead of decorating the whole controller.

如果您需要它们不可缓存,您还可以使用此属性装饰一些操作,而不是装饰整个控制器。

If your class or action didn't have NoCachewhen it was rendered in your browser and you want to check it's working, remember that after compiling the changes you need to do a "hard refresh" (Ctrl+F5) in your browser. Until you do so, your browser will keep the old cached version, and won't refresh it with a "normal refresh" (F5).

如果您的类或操作NoCache在浏览器中呈现时没有,并且您想检查它是否正常工作,请记住,在编译更改后,您需要在浏览器中执行“硬刷新”(Ctrl+F5)。在您这样做之前,您的浏览器将保留旧的缓存版本,并且不会使用“正常刷新”(F5)进行刷新。

回答by Jaguir

You can use the built in cache attribute to prevent caching.

您可以使用内置的缓存属性来防止缓存。

For .net Framework: [OutputCache(NoStore = true, Duration = 0)]

对于 .net 框架: [OutputCache(NoStore = true, Duration = 0)]

For .net Core: [ResponseCache(NoStore = true, Duration = 0)]

对于 .net 核心: [ResponseCache(NoStore = true, Duration = 0)]

Be aware that it is impossible to force the browser to disable caching. The best you can do is provide suggestions that most browsers will honor, usually in the form of headers or meta tags. This decorator attribute will disable server caching and also add this header: Cache-Control: public, no-store, max-age=0. It does not add meta tags. If desired, those can be added manually in the view.

请注意,无法强制浏览器禁用缓存。您能做的最好的事情是提供大多数浏览器都会接受的建议,通常以标题或元标记的形式。此装饰器属性将禁用服务器缓存并添加此标头:Cache-Control: public, no-store, max-age=0。它不添加元标记。如果需要,可以在视图中手动添加这些。

Additionally, JQuery and other client frameworks will attempt to trick the browser into not using it's cached version of a resource by adding stuff to the url, like a timestamp or GUID. This is effective in making the browser ask for the resource again but doesn't really prevent caching.

此外,JQuery 和其他客户端框架将尝试通过向 url 添加内容(例如时间戳或 GUID)来诱使浏览器不使用资源的缓存版本。这可以有效地使浏览器再次请求资源,但并不能真正阻止缓存。

On a final note. You should be aware that resources can also be cached in between the server and client. ISP's, proxies, and other network devices also cache resources and they often use internal rules without looking at the actual resource. There isn't much you can do about these. The good news is that they typically cache for shorter time frames, like seconds or minutes.

最后一点。您应该知道资源也可以缓存在服务器和客户端之间。ISP、代理和其他网络设备也会缓存资源,并且它们经常使用内部规则而不查看实际资源。对于这些,你无能为力。好消息是,它们通常缓存较短的时间范围,如秒或分钟。

回答by dfortun

In the controller action append to the header the following lines

在控制器操作中,将以下几行附加到标题

    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.

回答by Chris Moschini

All you need is:

所有你需要的是:

[OutputCache(Duration=0)]
public JsonResult MyAction(

or, if you want to disable it for an entire Controller:

或者,如果您想为整个控制器禁用它:

[OutputCache(Duration=0)]
public class MyController

Despite the debate in comments here, this is enough to disable browser caching - this causes ASP.Net to emit response headers that tell the browser the document expires immediately:

尽管这里的评论存在争议,但这足以禁用浏览器缓存 - 这会导致 ASP.Net 发出响应标头,告诉浏览器文档立即过期:

OutputCache Duration=0 Response Headers: max-age=0, s-maxage=0

OutputCache Duration=0 响应头:max-age=0, s-maxage=0

回答by Konamiman

Here's the NoCacheattribute proposed by mattytommo, simplified by using the information from Chris Moschini's answer:

这是NoCachemattytommo 提出的属性,使用 Chris Moschini 的回答中的信息进行了简化:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : OutputCacheAttribute
{
    public NoCacheAttribute()
    {
        this.Duration = 0;
    }
}

回答by Deepak

Output Caching in MVC

MVC 中的输出缓存

[OutputCache(NoStore = true, Duration = 0, Location="None", VaryByParam = "*")]

OR
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]

回答by Davut Gürbüz

For MVC6 (DNX), there is no System.Web.OutputCacheAttribute

对于 MVC6 ( DNX),没有System.Web.OutputCacheAttribute

Note: when you set NoStoreDuration parameter is not considered. It is possible to set an initial duration for first registration and override this with custom attributes.

注意:当您设置NoStoreDuration 参数时不考虑。可以为首次注册设置初始持续时间并使用自定义属性覆盖它。

But we have Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter

但是我们有 Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter

 public void ConfigureServices(IServiceCollection services)
        ...
        services.AddMvc(config=>
        {
            config.Filters.Add(
                 new ResponseCacheFilter(
                    new CacheProfile() { 
                      NoStore=true
                     }));
        }
        ...
       )

It is possible to override initial filter with a custom attribute

可以使用自定义属性覆盖初始过滤器

    [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);
        }
    }

Here is a use case

这是一个用例

    [NoCache]
    [HttpGet]
    public JsonResult Get()
    {            
        return Json(new DateTime());
    }

回答by Nenad

Correct attribute value for Asp.Net MVC Coreto prevent browser caching (including Internet Explorer 11) is:

用于防止浏览器缓存(包括Internet Explorer 11)的Asp.Net MVC Core 的正确属性值为:

[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]

as described in Microsoft documentation:

如 Microsoft 文档中所述:

Response caching in ASP.NET Core - NoStore and Location.None

ASP.NET Core 中的响应缓存 - NoStore 和 Location.None

回答by Csaba Toth

ASP.NET MVC 5 solutions:

ASP.NET MVC 5 解决方案:

  1. Caching prevention code at a central location: the App_Start/FilterConfig.cs's RegisterGlobalFiltersmethod:
  1. 在中心位置缓存预防代码:App_Start/FilterConfig.csRegisterGlobalFilters方法:
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // ...
            filters.Add(new OutputCacheAttribute
            {
                NoStore = true,
                Duration = 0,
                VaryByParam = "*",
                Location = System.Web.UI.OutputCacheLocation.None
            });
        }
    }
  1. Once you have that in place you my understanding is that you can override the global filter by applying a different OutputCachedirective at Controlleror Viewlevel. For regular Controller it's
  1. 一旦你有了它,我的理解是你可以通过OutputCacheControllerView级别应用不同的指令来覆盖全局过滤器。对于常规控制器,它是
[OutputCache(NoStore = true, Duration = 0, Location=System.Web.UI.ResponseCacheLocation.None, VaryByParam = "*")]

or if it's an ApiControllerit'd be

或者如果它ApiController

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, Location = System.Web.UI.OutputCacheLocation.None, VaryByParam = "*")]