OutputCache is sending wrong Vary header when the call hits the cache

前端 未结 3 2193
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-20 06:59

I have an action method that I want to cache:

[OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom=\"index\")]
public ActionResult Index()
         


        
相关标签:
3条回答
  • 2021-02-20 07:38

    I don't think the [OutputCache] attribute is what you want, the VaryByCustom method is basically saying that I want to cache different versions based on these parameters, it doesn't really have an option for Do Not Cache and the majority of the code in the attribute is built around server based caching.

    That being said the documentation on MSDN for custom caching seems to indicate you need to return a string to vary on based on the authentication state:

    public override string GetVaryByCustomString(HttpContext context, string custom)
    {
        if(custom == "user") return "User:" + context.Request.User.Identity.Name;
    
        return base.GetVaryByCustomString(context, custom);
    }
    

    And then use the user literal in the VaryByCustom:

    [OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom="user")]
    public ActionResult Index()
    {
        return View();
    }
    

    So basically this would result in a cache being built for anonymous (assuming the anonymous identity is empty string or something) and every user on the server, and a Vary: * sent to the client I believe. Obviously not ideal what you are looking for.

    If you really just want to cache the unauthenticated version using HTTP caching I would recommend not using the OutputCacheAttribute and using something more custom.

    You could easily just write in your own custom attribute something like what you have for your GetVaryByCustomString implementation (this is just some pseudo code, would need more than this):

    public class HttpCacheUnauthenticatedAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if(!filterContext.HttpContext.Request.IsAuthenticated) {
                //TODO: set unauthenticated caching values and vary here
            }
        }
    }
    

    And then tag your action method with it:

    [HttpCacheUnauthenticated]
    public ActionResult Index()
    {
        return View();
    }
    
    0 讨论(0)
  • 2021-02-20 07:41

    Sort of wrestling with something similar myself. Have you tried in the web.config to the setting omitVaryStar=true

    https://msdn.microsoft.com/en-us/library/ms228124(v=vs.100).aspx

    0 讨论(0)
  • 2021-02-20 07:45

    I am using a custom cache provider and in this case there is a simple solution for this. On the BeginRequest, based on the user authentication status, we set a context information to not run cache:

    HttpContext.Current.Items["NoCache"] = "1";
    

    And then on our GetVaryBy method we return null if this information is set:

    public override string GetVaryByCustomString(HttpContext context, string custom)
    {
        if (HttpContext.Current.Items["NoCache"] != null)
            return null;
    
        // remaining code here
    }
    

    And then on the cache methods, we can test the same. For instance:

    public override object Add(string key, object entry, DateTime utcExpiry)
    {
        if (HttpContext.Current.Items["NoCache"] != null)
            return null;
    
        // remaining code here
    }
    
    0 讨论(0)
提交回复
热议问题