的OutputCache发送错误Vary标头时调用命中缓存 [英] OutputCache is sending wrong Vary header when the call hits the cache

查看:118
本文介绍了的OutputCache发送错误Vary标头时调用命中缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我想缓存的操作方法:

I have an action method that I want to cache:

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

通过这种方式:

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    context.Response.Cache.SetOmitVaryStar(true);
    context.Response.Cache.VaryByHeaders["Cookie"] = true;

    if (User.Identity.IsAuthenticated)
    {
        Debug.Print("Authenticated");
        context.Response.Cache.SetNoServerCaching();
        context.Response.Cache.SetCacheability(HttpCacheability.Private);
        return null;
    }
    else
    {
        Debug.Print("Non authenticated");
        return custom;
    }
}

当时的想法是<一个href=\"http://stackoverflow.com/questions/9180954/cache-home-page-for-non-authenticated-users-in-asp-net-mvc-3\">keep对于非认证用户页面的缓存版本,但要避免缓存验证那些的。

我想它总是会返回一个有所不同:饼干 HTTP头,但事实并非如此。
这样做有一个提琴手试验和两次发出相同的请求,在第一HTTP调用它去好:

I thought it will always return a Vary:Cookie HTTP header, but it is not. Doing a test with Fiddler and issuing twice the same request, in the first HTTP call it goes good:

HTTP/1.1 200 OK
Cache-Control: public, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: Cookie
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:37 GMT
Content-Length: 441

但在第二个,它会覆盖头:

But in the second one, it overwrites the header:

HTTP/1.1 200 OK
Cache-Control: public, max-age=297
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:39 GMT
Content-Length: 441

所以,就我所知,浏览器将不缓存即使它是公共的,因为的要求有所不同:* 表示该请求已经与参数生成不在该URL也不在HTTP头。有没有办法来解决这个问题?

So, as far as I know, browsers won't cache the request even if it is public, since Vary:* means that the request has been generated with parameters that are not in the URL nor in the HTTP headers. Is there a way to fix this?

问候。

更新:

在以类似的方式,当我发送两个相同的身份验证请求,第一次调用得到私人修改,而不是因人而异标题:

In a similar way, when I send two identical authenticated requests, the first call gets the private modifier, but not the Vary header:

HTTP/1.1 200 OK
Cache-Control: private, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:43:14 GMT
Last-Modified: Thu, 09 Feb 2012 12:38:14 GMT
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:38:14 GMT
Content-Length: 443

但是,第二个得到相同的反应,非身份验证的请求:

But the second one gets the same response that a non-authenticated request:

HTTP/1.1 200 OK
Cache-Control: public, max-age=298
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:44:32 GMT
Last-Modified: Thu, 09 Feb 2012 12:39:32 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:39:33 GMT
Content-Length: 443

我已经上传出这一问题的测试项目等都可能是你想给它一个尝试。

I have uploaded a test project showing the issue so may be you want to give it a try.

请注意,有一个 IHttpModule的,设置一个请求已通过身份验证或不取决于该请求有一个cookie或没有,这不是一个真实生活的方式,它只是用于测试目的。

Please be aware that there is an IHttpModule that sets a request as authenticated or not depending on if the request has a cookie or not, this is not a "real life" approach, it is just for testing purposes.

该项目只包含一个网页的链接本身,在您登录的链接,并且会注销其他链接:

The project contains only a web page with a link to itself, a link that logs you in, and another link that logs you out:


  • 登陆:发送再次在 HTTP 302 重定向到主页一个cookie

  • 注销:发送在 HTTP 302 recirection到主页的过期饼干再次

  • LogIn : Sends a cookie in a HTTP 302 redirection to the home page again.
  • LogOut: Sends a expired cookie in a HTTP 302 recirection to the home page again.

预期/理想的行为将是:


  1. 用户访问索引,并从服务器获取页面。该页面显示日期A。

  2. 再度用户访问索引,浏览器显示缓存的页面稿。显示日期A。

  3. 清理浏览器缓存。

  4. 再度用户访问索引,浏览器显示服务器缓存版本。该页面显示日期A。

  5. 用户点击登录,并broswer得到一个新的页面,这显示日期B。

  6. 用户点击退出,以及浏览器获得服务器缓存页面。该页面显示日期A一次。

但是,这是行为至今:


  1. 用户访问索引,并从服务器获取页面。该页面显示日期A。

  2. 再度用户访问索引,浏览器显示缓存的页面稿。显示日期A。

  3. 清理浏览器缓存。

  4. 再度用户访问索引,浏览器显示服务器缓存版本。该页面显示日期A。

  5. 用户点击登录,并broswer得到一个新的页面,这显示日期B。

  6. 用户点击注销,并在浏览器的应该得到的服务器缓存的页面,但它并不。该页面显示日期从浏览器缓存B一次。这是因为缺乏在认证响应因人而异头的。

  1. User access Index, and get the page from the server. The page show date "A".
  2. User access Index again, and the browser shows the cached version.The page show date "A".
  3. Clean browser cache.
  4. User access Index again, and the browser shows the server cached version. The page show date "A".
  5. User clicks login, and the broswer gets a new page, that show date "B".
  6. User clicks logout, and the browser should get the server cached page, but it does not. The page show date "B" again from the browser cache. This is because the lack of the Vary header in the authenticated response.

我不知道如果我得到的东西错了缓存,只是缺少一些细节或的OutputCache 不工作得很好,但我会AP preciate任何指导。

I don't know if I get something wrong about caching, just missing some detail or the OutputCache does not work very well, but I would appreciate any guidance.

干杯。

更新2:

我的目的是使用HTTP缓存语义:

My intention is to use the HTTP cache semantics to:


  1. 允许浏览器和proxys缓存页面的公版。

  2. 允许浏览器缓存页面的认证版本其用户。

如果我改变的OutputCache声明做缓存只在服务器和prevent下游端和客户端的缓存:

If I change the OutputCache declaration to do the caching only on the server and prevent the downstream and client caching:

[OutputCache(Duration=60*5, Location=OutputCacheLocation.Server, VaryByCustom="index")]

它的行为如预期,但下游端和客户端缓存为prevented,那不是我想要的。

it behaves as expected, but the downstream and client cache is prevented, and that is not what I want.

推荐答案

我不认为 [的OutputCache] 属性是你想要什么,在 VaryByCustom是方法基本上是说,我想缓存基于这些参数不同的版本,它并没有真正对不缓存并多数人的一种选择在属性code是围绕基于服务器的缓存建造的。

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.

这是说在 MSDN 自定义缓存似乎表明你需要返回一个字符串,基于认证状态变化:

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

然后使用用户文字在 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.

如果你真的只是想用HTTP缓存,我建议不使用缓存未认证的版本 OutputCacheAttribute 和使用的东西更多的自定义。

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.

您可以很容易地就在自己编写自定义的属性类似,你有什么对你的 GetVaryByCustomString 的实施(这仅仅是一些伪code,将需要超过这一点):

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

这篇关于的OutputCache发送错误Vary标头时调用命中缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆