【问题标题】:ResponseCache attribute does not cache data on client sideResponseCache 属性不在客户端缓存数据
【发布时间】:2017-03-15 03:01:19
【问题描述】:

在 ASP.NET Core 应用程序中,我有一个返回一些数据的操作方法。我想在客户端缓存这些数据。所以基于documentation here 我可以在操作方法上使用ResponseCache 属性。此属性在响应中添加Cache-Control 标头

响应缓存是指在 HTTP 上指定缓存相关的 headers 由 ASP.NET Core MVC 操作做出的响应。这些标题指定如何 您希望客户端和中间(代理)机器缓存响应 某些请求(如果有的话)。这可以减少数量 请求客户端或代理向 Web 服务器发出请求,因为将来 相同动作的请求可以从客户端或代理的 缓存。

还有

响应缓存不会在 Web 服务器上缓存响应。它 与输出缓存不同,后者会将响应缓存在内存中 ASP.NET 和 ASP.NET MVC 早期版本中的服务器。

这就是我的操作方法的样子

public class LookupController : Controller
{
    [HttpGet]
    [ResponseCache(Duration = 120)]
    public IEnumerable<StateProvinceLookupModel> GetStateProvinces()
    {
        return _domain.GetStateProvinces();
    }
}

然后我使用浏览器将方法称为http://localhost:40004/lookup/getstateprovinces 这是请求和响应标头

请注意,响应标头具有预期的 Cache-Control: public,max-age-120。 但是,如果使用 F5(120 秒之前)刷新页面,GetStateProvince 操作方法中的调试器断点总是会命中。这意味着它不会在客户端缓存数据。

我还需要做些什么来启用客户端缓存吗?

更新 我尝试过使用 IE、Chrome 和 POSTMAN,但没有成功。每次我在地址栏中输入 url 或点击刷新时,客户端(即浏览器或邮递员)都会调用操作方法。

【问题讨论】:

  • @dotnetstep 是对的,据我所知,f5(refresh page) 已经是客户端的缓存代理。只需在地址栏中输入地址并输入。那就是我检查缓存的方式
  • @ergen 我也尝试过使用 POSTMAN,但没有成功
  • 我不知道邮递员是谁。让我们澄清一下:尝试简单地转到浏览器上的 url 而不是刷新。刷新是代理,其次文件类型对于客户端缓存很重要。例如,您不会缓存 1000 mb 视频。你只缓存一个.json,所以没关系。那么,我确信当你使用像 licalhost/lookup/getstateprovinces.json 这样的 url 时,你的缓存会起作用。专注于客户端的扩展和可缓存文件。即使您在响应中添加标头,由于扩展名,浏览器也可能不知道您的文件是静态文件
  • 我为什么要使用文件类型?它是一种动作方法。您永远不会将操作方法​​称为http://localhost/lookup/getstateprovinces.json。顺便说一句,这里是邮递员getpostman.com
  • 我没有说你应该使用文件类型。我说过,当您提供扩展名时,您会看到您的缓存会起作用。我建议你确保你的 _domain.GetStateProvinces();方法返回一个带有 .json 扩展名的有效 json。它只是一个结果,甚至不是没有扩展名的文件。认为您提供一个 .aspx 页面并命令浏览器缓存所有扩展名为 .aspx 的文件。摘要:尝试添加类似扩展或 mimetype 的东西(这取决于 your_domain.GetStateProvinces(); 方法返回的内容和方式),看看它是否有效

标签: asp.net-core asp.net-core-mvc asp.net-core-1.0 coreclr


【解决方案1】:

实际上 ResponseCache 属性按预期工作。
不同之处在于,如果您浏览网站页面(案例 1)或使用后退和前进按钮(刷新页面时不会),则会缓存响应。

作为案例1的一个例子,我有以下几点:

正如您将在文章Response Caching in ASP.Net Core 1.1 中看到的,声明如下:

在浏览器会话期间,浏览网站内的多个页面或使用后退和前进按钮访问页面,内容将从本地浏览器缓存中提供(如果未过期)。
但是当页面被通过 F5 刷新,请求将转到服务器并刷新页面内容。您可以使用 F5 刷新联系页面来验证它。
因此,当您按下 F5 时,响应缓存过期值对服务内容没有任何作用。您应该会看到联系请求的 200 响应。

参考:
[1]。 ASP.NET Core Response Caching Sample
[2]。 ResponseCache attribute sample
[3]:How to control web page caching, across all browsers?

【讨论】:

  • Index 操作方法返回 View 所以你说的可能是真的(我还没有尝试过)。但是我的问题与以 JSON 格式返回数据的操作方法有关。就像我在问题中发布的一样。
  • 如果您使用的是浏览器并且您在获得缓存响应时处于那些指定的情况下,则 Content-Type 无关紧要。关于 Postman,如果您将其作为独立应用程序安装(从他们的网站下载),您将无法缓存您的请求。但是,如果您将其作为应用程序安装到 Google Chrome 中,您将设法获得缓存的响应。我会在答案中添加必要的信息。
【解决方案2】:

长话短说,使用像下面这样的 ResponseCache 属性足以让基于过期的客户端缓存在全新的默认 dotnet 核心项目中工作(包括 async 方法):

[HttpGet]
[ResponseCache(Duration = 120)]
public IEnumerable<StateProvinceLookupModel> GetStateProvinces()
{
    return _domain.GetStateProvinces();
}

这在上面的屏幕截图中正常工作,因为在那里可以看到Cache-Control: public,max-age=120。在大多数情况下,浏览器不会在到期前(即接下来的 120 秒或 2 分钟)发送后续请求,但这是由浏览器(或其他客户端)决定的。

如果请求 无论如何都发送了,您要么有一些中间件或服务器配置覆盖了您的响应标头,要么您的客户端忽略了缓存指令。在上面的截图中,客户端忽略了缓存,因为缓存控制头在那里。

忽略客户端缓存而发送请求的常见情况:

  • Chrome prevents 在没有证书的情况下使用 HTTPS 时的任何类型的缓存(或无效证书,这在本地开发中通常很常见,因此在测试缓存时请确保使用 HTTP,或信任自签名证书)
  • 大多数浏览器开发工具在打开时默认禁用缓存,这个可以禁用
    • 浏览器通常会发送额外的标头,Chrome 会发送Cache-Control: no-cache
  • 直接刷新(即 Ctrl+F5)将指示大多数浏览器不使用缓存并发出请求而不管年龄
    • 浏览器通常会发送额外的标头,Chrome 会发送 Cache-Control: max-age=0(这在您的屏幕截图中可见)
  • Postman 发送Cache-Control: no-cache 标头使其绕过本地缓存,导致请求被发送;您可以从设置对话框中禁用它,在这种情况下,将不再使用上述客户端缓存配置发送请求

此时我们已经超越了基于过期的客户端缓存,而服务器以一种或另一种方式接收请求,并发生另一层缓存:你可以让服务器响应一个304 Not Modified 代码(然后再次由客户端以它想要的任何方式解释)或使用服务器端缓存并以完整内容响应。或者您可能不使用任何后续缓存,而只是在服务器上再次执行整个请求处理。


注意:ResponseCache 属性不要与启动配置中的 services.AddResponseCaching()app.UseResponseCaching() 中间件混淆,因为那是用于服务器端缓存(默认情况下使用内存缓存,使用中间件时)。客户端缓存不需要中间件,属性本身就足够了。

【讨论】:

    【解决方案3】:

    首先我想澄清几件事,我相信你已经知道了。

    1. ResponseCache 无论如何都不等于 OutputCache。

    2. ResponseCache 符合我的想法,但它不会在服务器端缓存任何内容。

    现在,如果您想缓存与 OutputCache 相同的缓存,那么您可能必须使用刚刚发布的预览版 1.1。

    ASP.net core 1.1 预览版

    https://blogs.msdn.microsoft.com/webdev/2016/10/25/announcing-asp-net-core-1-1-preview-1/

    他们引入了新的响应缓存中间件。响应缓存中间件

    这里有它的演示。 https://github.com/aspnet/ResponseCaching/blob/dev/samples/ResponseCachingSample/Startup.cs

    【讨论】:

    • 我从来没有说过我想像 outputcache 一样在服务器端缓存,事实上我不想在服务器端缓存,我想在客户端缓存数据。这就是ResponseCache 属性应该做的事情
    猜你喜欢
    • 2019-02-15
    • 1970-01-01
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2021-11-07
    • 2017-03-18
    • 2012-07-26
    相关资源
    最近更新 更多