【问题标题】:Add Cache to ASP.NET Core response将缓存添加到 ASP.NET Core 响应
【发布时间】:2020-08-10 23:07:54
【问题描述】:

我使用 ASP.NET Core 3.1 创建了如下中间件:

public class SitemapMiddleware {
  
  private readonly RequestDelegate _next;

  public SitemapMiddleware(RequestDelegate next) {
    
    _next = next;

  }

  public async Task InvokeAsync(HttpContext context, ISitemapService sitemapService) {

    if (context.Request.Path.StartsWithSegments("sitemap.xml")) {

      Sitemap sitemap = await sitemapService.GetAsync();

      context.Response.ContentType = "application/xml";

      context.Response.Headers.Add("Cache-Control", "public,max-age=20");

      await context.Response.WriteAsync(sitemap.Build(), Encoding.UTF8);

    } else {

      await _next(context);
    
    }

  }

}

当我在浏览器中访问“sitemap.xml”时,我得到的响应内容正确。

但是当我在接下来的 20 秒内再次访问它时,代码会再次执行。

我正在添加“Cache-Control”标头,我检查了它,它在响应中。

为什么代码又被执行了?

【问题讨论】:

  • 是否需要添加Caching Middleware
  • 我在 ConfigureServices 中有 services.AddResponseCaching(); 在 Configure 方法中有 applicationBuilder.UseResponseCaching();。我不知道是否缺少某些东西......
  • 在开发者选项下的浏览器上(在 chrome F12/Network 上)通常有一个“禁用缓存”选项。值得一试。
  • 我知道那个选项并且我启用了缓存...

标签: asp.net-core asp.net-core-3.1


【解决方案1】:

可能是您的浏览器忽略了缓存控制标头。问题Is Chrome ignoring Cache-Control: max-age? 指出:

如果您在对同一选项卡中的同一 URI 的另一个请求之后立即发出请求(通过单击刷新按钮、按 F5 键或按 Command + R),Google Chrome 会忽略 Cache-Control 或 Expires 标头。

Firefox 似乎也在做同样的事情。

经过快速测试,在另一个选项卡上加载相同的 URL 确实会加载缓存的内容,并且不会再次执行代码。

【讨论】:

  • 你完全正确。我尝试在另一个选项卡中调用url,代码没有执行,返回缓存的版本。
【解决方案2】:

如果不想依赖 HTTP 缓存,可以使用 ASP.NET 缓存,例如内存缓存。我整理了一个与我使用的类似的小例子。可能会有所帮助。

public class SitemapController : Controller
        {
            const string SITEMAP_CACHE_KEY = "SitemapNodesCacheKey";
    
        readonly IMemoryCache cache;

        public SitemapController(IMemoryCache cache)
        {
            this.cache = cache;
        }

        /// <summary>
        /// Returns sitemap of this web.
        /// Handles caching etc.
        /// </summary>
        /// <returns></returns>
        protected string GetSitemap()
        {
            //Cache not found
            if (!cache.TryGetValue(SITEMAP_CACHE_KEY, out var cacheEntry))
            {
                cacheEntry = "SOME CACHE TEXT/STRUCTURE HERE";

                //Set cache options
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                    .SetSlidingExpiration(TimeSpan.FromHours(8))
                    .SetAbsoluteExpiration(TimeSpan.FromHours(24));

                //Save data in cache
                cache.Set(SITEMAP_CACHE_KEY, cacheEntry, cacheEntryOptions);
            }


            return cacheEntry as string;
        }

        [HttpPost("/sitemap/update")]
        public IActionResult UpdateSitemap()
        {
            cache.Remove(SITEMAP_CACHE_KEY);

            return Ok();
        }

        [Route("/sitemap.xml")]
        public IActionResult SitemapFile()
        {
            return Content(GetSitemap(), "text/xml");
        }
    }

【讨论】:

  • 我也在使用 MemoryCache,但我不确定这是否是最佳选择。事实上,“sitemap.xml”将被 Google 和 Bing 站点地图调用。不是通过浏览器。你认为我应该使用 MemoryCache 而不是 Cache Control 吗?
  • 如果你有一个静态的 sitemap.xml 文件,我相信绝对不需要缓存系统。如果您的站点地图是例如从数据库生成的并且您担心性能,我个人建议使用内存缓存(IMemoryCache),因为正如您所说,站点地图文件通常是由搜索引擎请求的,它为您提供更多“控制“——你完全知道它会如何表现。没有意想不到的恶作剧。但是,如果我们要谈论图像、页面等,情况可能就不同了。
猜你喜欢
  • 1970-01-01
  • 2018-02-08
  • 2022-06-11
  • 2018-03-11
  • 2022-11-17
  • 2018-06-05
  • 1970-01-01
  • 2020-10-20
  • 2018-02-21
相关资源
最近更新 更多