ASP.NET Core 响应缓存中间件 - 如何停止缓存 (500) 错误响应

Thi*_*iri 10 c# asp.net-core responsecache asp.net-core-webapi

我在应用程序中实现了 ASP.NET Core 响应缓存来缓存一些 API 请求。

我已将 ResponseCaching 中间件添加到 ConfigureServices 方法中的 IServicesCollection 中,如下所示。

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
            builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyHeader()
                       .AllowAnyMethod();

            });
        });

        services.AddResponseCaching();
        services.AddControllersWithViews();

        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
    }
Run Code Online (Sandbox Code Playgroud)

我已经在像这样的配置方法中使用了它。

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
        app.UseCors("CorsPolicy");
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        if (!env.IsDevelopment())
        {
            app.UseSpaStaticFiles();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
        });

        app.UseResponseCaching();

        app.Use(async (context, next) =>
        {
           context.Response.GetTypedHeaders().CacheControl =
              new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
              {
                  Public = true,
                  MaxAge = TimeSpan.FromSeconds(apiConfiguration.CacheDuration),
              };

        context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = new string[] { "Accept-Encoding" };
     
            await next();
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";
            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)

我还使用 ResponseCache 属性装饰了我的 Web API 操作方法,如下所示

    [HttpGet]
    [ResponseCache(Duration = 60)]
    public IActionResult Get(){
      //code
    }
Run Code Online (Sandbox Code Playgroud)

最后,在我的角度应用程序中,我也设置了缓存控制标头。

  fetchAPIData(){
    return this.http.get('https://localhost:44325/data',  {
      headers: new HttpHeaders({
        'Cache-Control': 'public',
        "Content-Type": "application/json"
      })
    });
  }
Run Code Online (Sandbox Code Playgroud)

我只想缓存状态代码为 200(正常)的服务器响应。根据微软的文档,应该可以工作

响应缓存中间件仅缓存导致 200 (OK) 状态代码的服务器响应。任何其他响应(包括错误页面)都会被中间件忽略。

但当它运行时,它也会缓存 500 个错误响应。看下图 在此输入图像描述

  1. 这可能是什么原因?
  2. 我应该做什么来解决这个问题。我只想缓存 200 个(OK)请求。

笔记

  • 我也尝试过 Chrome、Edge 和 IE 浏览器。
  • 我使用的是 ASP.NET Core 3.1
  • 我的前端应用程序是 Angular 7

小智 6

我确实遇到了问题中描述的问题。我在 Web api 端点上使用 ResponseCache 属性,该属性可以返回成功或失败。我正在获取调用成功和失败的缓存标头。

我通过添加自定义中间件来删除失败情况下的缓存标头解决了这个问题:

app.Use(async (context, next) =>
{
    // Do not cache error conditions
    context.Response.OnStarting(() =>
    {
        if (context.Response.StatusCode >= 400)
        {
            context.Response.Headers.Remove("Cache-Control");
        }
        return Task.FromResult(0);
    });
    await next();
});
Run Code Online (Sandbox Code Playgroud)