Prevent Caching in ASP.NET MVC for specific action

2019-01-01 03:01发布

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.

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?

8条回答
梦寄多情
2楼-- · 2019-01-01 03:42

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:

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

查看更多
荒废的爱情
3楼-- · 2019-01-01 03:43

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

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

For .net Core: [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.

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.

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.

查看更多
萌妹纸的霸气范
4楼-- · 2019-01-01 03:44

Output Caching in MVC

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

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

查看更多
皆成旧梦
5楼-- · 2019-01-01 03:48

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.
查看更多
千与千寻千般痛.
6楼-- · 2019-01-01 03:49

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

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

But we have 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());
    }
查看更多
伤终究还是伤i
7楼-- · 2019-01-01 03:57

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

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : OutputCacheAttribute
{
    public NoCacheAttribute()
    {
        this.Duration = 0;
    }
}
查看更多
登录 后发表回答