You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 3.1如何实现服务端全响应缓存及缓存失效?

解决方案:ASP.NET Core 3.1 服务器端页面缓存(支持手动失效)

刚好我之前帮朋友解决过类似的迁移问题,你提到的需求——在服务器内存中缓存完整响应、设置30天过期、支持手动清除缓存,确实没法靠[ResponseCache]属性或默认的<cache>标签助手直接实现,我给你整理一套落地的方案:

先理清现有方案的局限性

  • [ResponseCache(Duration = 30)]:本质是给客户端发缓存头,让浏览器/代理去缓存内容,服务器每次还是会重新生成响应,完全达不到减少服务器计算量的目的。
  • <cache>标签助手:虽然能做服务器端缓存,但默认配置下没法灵活实现全局手动失效指定缓存项,而且长周期(30天)的缓存配置也不够友好。

具体实现步骤

1. 自定义服务器端页面缓存过滤器

我们自己写一个Action过滤器,拦截请求和响应:先查缓存,有缓存直接返回;没缓存就执行页面逻辑,把生成的响应存入内存缓存。

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
using System.IO;
using System.Text;
using System.Threading.Tasks;

public class ServerSidePageCacheAttribute : ActionFilterAttribute
{
    private readonly int _cacheDurationDays;
    private const string _cacheKeyPrefix = "PageCache_";

    public ServerSidePageCacheAttribute(int cacheDurationDays)
    {
        _cacheDurationDays = cacheDurationDays;
    }

    public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        // 生成唯一缓存键:路由+查询参数,确保不同请求的缓存独立
        var cacheKey = $"{_cacheKeyPrefix}{context.HttpContext.Request.Path}{context.HttpContext.Request.QueryString}";
        var memoryCache = context.HttpContext.RequestServices.GetService(typeof(IMemoryCache)) as IMemoryCache;

        // 命中缓存直接返回
        if (memoryCache.TryGetValue(cacheKey, out string cachedContent))
        {
            context.HttpContext.Response.ContentType = "text/html";
            await context.HttpContext.Response.WriteAsync(cachedContent, Encoding.UTF8);
            return;
        }

        // 拦截响应流,保存页面输出
        var originalResponseStream = context.HttpContext.Response.Body;
        using var memoryStream = new MemoryStream();
        context.HttpContext.Response.Body = memoryStream;

        // 执行页面逻辑,生成原始响应
        await next();

        // 将响应内容存入内存缓存,设置30天过期
        memoryStream.Seek(0, SeekOrigin.Begin);
        using var reader = new StreamReader(memoryStream);
        var content = await reader.ReadToEndAsync();

        var cacheOptions = new MemoryCacheEntryOptions()
            .SetAbsoluteExpiration(System.TimeSpan.FromDays(_cacheDurationDays));

        memoryCache.Set(cacheKey, content, cacheOptions);

        // 把缓存的内容写回原始响应流,正常返回给客户端
        memoryStream.Seek(0, SeekOrigin.Begin);
        await memoryStream.CopyToAsync(originalResponseStream);
        context.HttpContext.Response.Body = originalResponseStream;
    }
}

2. 在Razor Page上应用缓存过滤器

直接在你的IndexModel上添加自定义属性,指定30天缓存:

[ServerSidePageCache(30)]
public class IndexModel : PageModel
{
    private readonly ILogger<IndexModel> _logger;
    public IndexModel(ILogger<IndexModel> logger)
    {
        _logger = logger;
    }
    public void OnGet() { }
}

3. 实现手动清除缓存的功能

写一个缓存失效服务,用来在后台修改内容后,精准清除对应页面的缓存:

using Microsoft.Extensions.Caching.Memory;

public class CacheInvalidationService
{
    private readonly IMemoryCache _memoryCache;
    private const string _cacheKeyPrefix = "PageCache_";

    public CacheInvalidationService(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    // 根据页面路径+查询参数清除指定缓存
    public void InvalidatePageCache(string pagePath, string queryString = "")
    {
        var cacheKey = $"{_cacheKeyPrefix}{pagePath}{queryString}";
        _memoryCache.Remove(cacheKey);
    }

    // 可选:清除所有页面缓存
    // 注意:IMemoryCache没有直接批量清除的方法,需要额外维护缓存键集合
    // 比如添加缓存时把键存入ConcurrentDictionary,这里遍历移除即可
}

然后在Startup.cs里注册这个服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMemoryCache();
    services.AddScoped<CacheInvalidationService>();
    // 其他服务注册...
}

之后你就可以在后台管理页面或者API接口里,注入CacheInvalidationService,调用InvalidatePageCache("/")来清除首页的缓存了。

额外补充

  • 缓存键定制:如果需要个性化缓存(比如不同用户看到不同内容),可以在缓存键里加入用户ID等标识。
  • 多服务器场景:如果你的应用是集群部署,单机内存缓存就不够用了,把IMemoryCache换成IDistributedCache(比如Redis),逻辑基本一致。
  • 内存占用优化:大页面缓存会占用较多内存,可以根据实际情况调整缓存过期策略,或者限制缓存的总大小。

内容的提问来源于stack exchange,提问作者Alireza Noori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:08:11