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

.NET Web API自定义CacheFilter缓存不生效问题排查

问题原因及解决方案

你当前实现的CacheFilter仅完成了客户端缓存响应头配置,没有实现服务端侧的响应缓存逻辑,这是预期不生效的核心原因,具体存在两点问题:

  • 你设置的CacheControl响应头仅用于告知客户端/代理节点如何缓存当前响应,不会阻止请求打到服务端:只要请求到达服务端,GetGuid方法都会执行生成新的Guid,你配置的100秒缓存只是客户端本地的缓存规则,如果你是强制刷新页面、或者客户端配置了忽略缓存,请求仍会触发服务端逻辑。
  • 你没有实现缓存命中的拦截逻辑:即使客户端携带缓存验证头发起请求,你的过滤器也没有做有效性校验,仍会完整执行Action逻辑返回新结果。

方案1:使用官方成熟的响应缓存组件(推荐)

ASP.NET Web API 2 可直接安装Microsoft.AspNet.WebApi.OutputCache NuGet包,直接使用特性标记即可,无需自己实现过滤逻辑:

// 安装包后直接标记方法即可
[CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)]
public Guid GetGuid()
{
    return Guid.NewGuid();
}

如果是ASP.NET Core Web API,直接使用原生的[ResponseCache]特性,同时在Program.cs中开启响应缓存中间件即可。


方案2:完善自定义CacheFilter逻辑

如果需要自己实现缓存逻辑,需要同时实现请求前缓存校验和请求后缓存存储两个逻辑,参考代码如下:

public class CacheFilter : ActionFilterAttribute
{
    public int TimeDurationInSecs { get; set; }
    // 用MemoryCache做服务端缓存存储,多实例部署可替换为分布式缓存
    private static readonly MemoryCache _cache = MemoryCache.Default;

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        // 生成唯一缓存key:包含控制器名、Action名、请求参数
        var key = $"{actionContext.ControllerContext.ControllerDescriptor.ControllerName}_{actionContext.ActionDescriptor.ActionName}_{string.Join("_", actionContext.ActionArguments.Select(kv => kv.Value))}";
        var cachedResponse = _cache.Get(key) as HttpResponseMessage;
        if (cachedResponse != null)
        {
            // 缓存命中直接返回缓存结果,不执行Action
            actionContext.Response = cachedResponse;
            return;
        }
        base.OnActionExecuting(actionContext);
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null && actionExecutedContext.Response.IsSuccessStatusCode)
        {
            // 生成和OnActionExecuting一致的缓存key
            var key = $"{actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerName}_{actionExecutedContext.ActionContext.ActionDescriptor.ActionName}_{string.Join("_", actionExecutedContext.ActionContext.ActionArguments.Select(kv => kv.Value))}";
            // 把响应存入缓存
            _cache.Add(key, actionExecutedContext.Response, DateTimeOffset.Now.AddSeconds(TimeDurationInSecs));
            // 配置客户端缓存头
            actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue
            {
                MaxAge = TimeSpan.FromSeconds(TimeDurationInSecs),
                MustRevalidate = true,
                Public = true
            };
        }
        base.OnActionExecuted(actionExecutedContext);
    }
}

内容的提问来源于stack exchange,提问作者JS.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 19:54:00