ASP.NET Core 项目中响应缓存不起作用

11

我尝试在ASP.NET Core项目中实现响应缓存,但它没有起作用。这是 startup.cs 代码:

public void ConfigureServices(IServiceCollection services) 
{
  services.AddResponseCaching();
  services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env) 
{
    app.UseResponseCaching();

    if (env.IsDevelopment()) 
    {
      app.UseDeveloperExceptionPage();
    }

这是我的控制器。

[ResponseCache(Duration = 30)]
public IActionResult Index() 
{
  ViewBag.IsMobile = RequestExtensions.IsMobileBrowser(ContextAccessor.HttpContext.Request);
  return View();
}

但是仍需缓存控制头标识。

cache-control →no-cache, no-store

请帮忙看一下哪里出了问题。这个响应缓存没有生效,我查看了微软的文档并进行了相应调整。


有没有演示可以重现你的问题?尝试使用CacheController [https://github.com/Edward-Zhou/AspNetCore/blob/master/MVCPro/Controllers/CacheController.cs#L12] 进行测试,以检查它是否与你的环境有关。 - Edward
5个回答

14
注意,为使缓存起作用,必须满足以下一些要求:

请求必须从服务器返回200 (OK)响应。

请求方法必须是GET或HEAD。

终端中间件(例如静态文件中间件)在响应被 Response Caching 中间件处理之前,不得对其进行处理。

Authorization头不能存在。

Cache-Control头参数必须有效,并且响应必须标记为public且未标记为private。

如果Cache-Control头不存在,则Pragma: no-cache 头/值不能存在,因为当Cache-Control头存在时,它会覆盖Pragma头。Set-Cookie头不能存在。

Vary头参数必须有效且不能等于 *。

Content-Length 头值(如果设置)必须与响应正文的大小相匹配。

...

请参阅此网站:aspnet-core-response-cache

还要注意,如果请求来自Postman,请禁用“不发送缓存标头”选项。

请参阅此帖子(最后一张图片): ASP.Net Core 2.0 - ResponseCaching Middleware - Not Caching on Server


感谢这个sanmolhec,vary头和postman提示真的帮了我很多。 - darkezm0

4

要在Dotnet Core中设置响应缓存,请按照以下步骤进行:

  1. In Startup.cs locate the ConfigureServices method and add the following line:

    services.AddResponseCaching();

  2. Ins Startup.cs locate the Configure method and add the following lines:

        app.UseResponseCaching();
    
        app.Use(async (context, next) =>
        {
            context.Response.GetTypedHeaders().CacheControl =
                new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
                {
                    Public = true,
                    MaxAge = TimeSpan.FromSeconds(10)
                };
            context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] =
                new string[] { "Accept-Encoding" };
    
            await next();
        });
    
  3. Apply the [ResponseCache] attribute to the action which requires caching:

    [ResponseCache(Duration = 300, VaryByQueryKeys = new string[] { "id" })]
    [HttpGet]
    public async Task<IActionResult> Index(int id)
    {
        return View();
    }
    

你能否请看一下我发布的问题吗? https://stackoverflow.com/questions/72755972/netcore-responsecache-does-not-work-for-some-routes - Offir

2

我尝试了这份由微软提供的文档,并成功地进行了缓存。

Cache-Control: public,max-age=30
Date: Thu, 27 Dec 2018 07:50:16 GMT

我认为你遗漏了 app.Use(async => ) 这部分。


1
添加了这个之后,它没有显示任何缓存控制。 - Devloper

1

使 ResponseCaching 正常工作需要以下几个步骤:

  1. 在 Startup.cs 中正确调用 AddResponseCaching()UseResponseCaching()
  2. 页面必须返回 Cache-Control 头,例如 Cache-Control: public,max-age=60(注意它必须包含 public 指令)。您可以通过 [ResponseCache] 属性、手动添加到响应头等方式实现。
  3. 方法必须是 GET 或 HEAD,状态码必须为 200
  4. 授权请求头必须不存在
  5. 如果客户端在请求中发送了自己的缓存控制头,则它必须是有效的 - 即如果客户端传递了 Cache-Control: max-age=0(Chrome/Firefox 等在用户按 F5 时会这样做),则响应将永远不会从缓存中提供,因为任何缓存都定义比 0 秒更旧
  6. 其他各种条件。我建议确保您可以看到来自 Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware 的调试级别日志,它将输出它不缓存请求的原因
在我的情况下,我想要忽略客户端请求的 Cache-Control 标头,因此我添加了一个 ResponseCachingPolicyProvider 的子类,如下所示:
    /// <summary>
    /// By default, <see cref="ResponseCachingPolicyProvider"/> will not return a cached response
    /// if the client sends up a Cache-Control header indicating the client wants a fresh
    /// response. This is according to HTTP spec but is not the behavior we want, so
    /// we will remove the client's specified Cache-Control header while evaluating whether
    /// or not we should return the cached response for this request.
    /// </summary>
    public class CustomResponseCachingPolicyProvider : ResponseCachingPolicyProvider
    {
        public override bool IsCachedEntryFresh(ResponseCachingContext context)
        {
            var reqCacheControl = context.HttpContext.Request.Headers[HeaderNames.CacheControl];
            context.HttpContext.Request.Headers.Remove(HeaderNames.CacheControl);
            var result = base.IsCachedEntryFresh(context);
            context.HttpContext.Request.Headers.Add(HeaderNames.CacheControl, reqCacheControl);
            return result;
        }
    }

如果请求是从内存缓存中提供的,它将在响应中添加一个“Age”头,您可以检查以验证缓存是否按预期运行。

0

你的操作必须是GET方法

为你的操作添加HttpGet属性

[ResponseCache(Duration = 30)]
[HttpGet] // <---- 
public IActionResult Index() 
{
  ViewBag.IsMobile = RequestExtensions.IsMobileBrowser(ContextAccessor.HttpContext.Request);
  return View();
}

GET是控制器操作中的默认HTTP动词,且是可选的。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接