【问题标题】:ASP.NET MVC Page with ResponseCache on action DOES return new content instead of cache带有 ResponseCache 的 ASP.NET MVC 页面确实返回新内容而不是缓存
【发布时间】:2021-01-31 07:09:26
【问题描述】:

我按照本教程 (https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-2.1) 在我的控制器操作上实现了 ResponseCache。

简而言之,我添加了 services.AddResponseCaching();app.UseResponseCaching(); 在启动中,这个标签 [ResponseCache( Duration = 30)] 在我的控制器上。

然后我在我的视图中添加了一个<h2>@DateTime.Now</h2>,而我所期望的......是相同的 datetime.now 30 秒。

但它没有,它只是在每次重新加载时显示新时间 (F5)。

我确保我在 chrome 中的 devtools 没有说“禁用缓存”。

在我的本地机器上打开和不打开 chrome devtools,现在正在尝试一个全新的 .net core mvc 项目。

我注意到的一件事(打开 devtools)是请求有这个标头:Cache-Control: max-age=0。这会影响行为吗? 我认为这意味着什么,因为它看起来像请求说“没有缓存”,但这让我觉得很奇怪,因为我没有把标题放进去,我会说 chrome 的默认行为不会忽略缓存?

【问题讨论】:

    标签: caching asp.net-core-mvc


    【解决方案1】:

    Cache-Control: max-age=0 这样的标头有效地禁用了所有缓存。资源基本上一掉线就过期了,所以它们总是被获取。此标头源自服务器。与客户无关。

    假设您没有意外以某种方式手动禁用响应缓存。然后,最有可能的情况是您正在做一些响应缓存中间件永远不会缓存的事情。 documentation 列出了在缓存响应之前必须满足的以下条件,无论您做什么:

    • 请求必须产生带有 200 (OK) 状态代码的服务器响应。
    • 请求方法必须是 GET 或 HEAD。
    • 终端中间件(例如静态文件中间件)不得在响应缓存中间件之前处理响应。
    • 授权标头不得存在。
    • Cache-Control 标头参数必须有效,并且响应必须标记为公共而不标记为私有。
    • 如果 Cache-Control 标头不存在,则 Pragma: no-cache 标头不得存在,因为 Cache-Control 标头在存在时会覆盖 Pragma 标头。
    • Set-Cookie 标头不得存在。
    • Vary 标头参数必须有效且不等于 *。
    • Content-Length 标头值(如果已设置)必须与响应正文的大小匹配。
    • 未使用 IHttpSendFileFeature。
    • 响应不能像 Expires 标头以及 max-age 和 s-maxage 缓存指令所指定的那样陈旧。
    • 响应缓冲必须成功,并且响应的大小必须小于配置或默认的 SizeLimit。
    • 根据 RFC 7234 规范,响应必须是可缓存的。例如,请求或响应头字段中不得存在 no-store 指令。有关详细信息,请参阅第 3 节:将响应存储在 RFC 7234 的缓存中。

    但是,在这种情况下,服务器应该发送Cache-Control: no-cache,而不是max-age=0。结果,我倾向于在某个地方进行一些错误配置,您已经设置了这个最大年龄值并且忘记或忽略了它。

    【讨论】:

    • 感谢您的回复。我的第一反应是我没有做任何特别的事情,因为我将问题隔离在一个新的基本 asp.net mvc 核心项目中。昨天我“使用”了索引操作,现在我用新的操作方法重试了,由于某种我不明白的原因,它现在发送标题Cache-Control: public,max-age=100。所以一定有什么改变了,但我不知道是什么。
    • 我还注意到,当我通过菜单导航时,浏览器尊重缓存(时间保持不变,devtools 中的结果显示“来自磁盘缓存”)但是当我点击 F5 时浏览器决定重新加载页面。
    • 如果不能看到您的代码库,就很难确切地说出来。但是,重要的是要意识到缓存客户端完全取决于客户端。 Cache-Control 标头仅允许服务器就可以缓存哪些资源以及如何缓存提出建议。客户可以完全无视它。因此,缓存行为将在很大程度上取决于客户端(即 Web 浏览器),并且不同的 Web 浏览器可能会选择不同的处理方式,即一个人可能决定通过从服务器请求所有新内容来处理 F5。
    • 非常感谢您的解释。
    【解决方案2】:

    这在 3.1 应用程序中对我有用,不允许 F5/Ctrl+F5 或 Firefox 或 Chrome 中的开发人员工具绕过服务器缓存以获得完整响应。

    在启动时在UseResponseCaching()之前添加这个小中间件。

    // Middleware that fixes server caching on F5/Reload
    app.Use(async (context, next) =>
    {
        const string cc = "Cache-Control";
    
        if (context.Request.Headers.ContainsKey(cc))
        {
            context.Request.Headers.Remove(cc);
        }
    
        const string pragma = "Pragma";
    
        if (context.Request.Headers.ContainsKey(pragma))
        {
            context.Request.Headers.Remove(pragma);
        }
    
        await next();
    });
    
    app.UseResponseCaching();
    

    没有发现任何问题...

    【讨论】:

      猜你喜欢
      • 2012-06-02
      • 1970-01-01
      • 2013-01-06
      • 2016-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多