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

ASP.NET Core如何仅在启用响应缓存时按查询字符串区分缓存

实现方案

不要直接在控制器上硬编码带VaryByQueryKeys的[ResponseCache]特性,通过ASP.NET Core的应用模型约定,在启动阶段检测消费端是否注册了响应缓存服务,再动态给类库内的控制器追加对应配置,即可兼容两种运行场景,不会抛出异常。

具体实现步骤

  • 编写自定义控制器模型约定,针对类库内的控制器按需加载缓存规则:
public class LibraryControllerResponseCacheConvention : IControllerModelConvention
{
    private readonly bool _isResponseCachingEnabled;

    public LibraryControllerResponseCacheConvention(bool isResponseCachingEnabled)
    {
        _isResponseCachingEnabled = isResponseCachingEnabled;
    }

    public void Apply(ControllerModel controller)
    {
        // 仅匹配当前类库下的控制器,避免影响消费端的其他控制器
        if (controller.ControllerType.Assembly != typeof(ClassLibraryController).Assembly)
        {
            return;
        }

        var cacheAttribute = new ResponseCacheAttribute
        {
            Duration = int.MaxValue,
            Location = ResponseCacheLocation.Any
        };

        // 仅在消费端启用响应缓存时,才设置VaryByQueryKeys规则
        if (_isResponseCachingEnabled)
        {
            cacheAttribute.VaryByQueryKeys = new[] { "*" };
        }

        controller.Filters.Add(cacheAttribute);
    }
}
  • 给类库添加控制器注册扩展方法,自动完成服务检测和约定注入,消费端不需要编写额外逻辑:
public static class MvcBuilderExtensions
{
    public static IMvcBuilder AddLibraryControllers(this IMvcBuilder builder)
    {
        // 检测消费端是否已经调用AddResponseCaching注册了响应缓存服务
        bool hasResponseCachingService = builder.Services.Any(s => 
            s.ServiceType == typeof(IResponseCachingPolicyProvider)
        );

        // 加载类库的控制器程序集
        builder.AddApplicationPart(typeof(ClassLibraryController).Assembly);
        // 注入自定义缓存约定
        builder.Services.Configure<MvcOptions>(options =>
        {
            options.Conventions.Add(new LibraryControllerResponseCacheConvention(hasResponseCachingService));
        });

        return builder;
    }
}

运行效果

  • 消费端未启用响应缓存(未调用AddResponseCaching()、未注册响应缓存中间件):仅给响应添加public缓存头,和原有逻辑完全一致,不会抛出异常
  • 消费端启用响应缓存:自动追加VaryByQueryKeys = new[] {"*"}配置,响应会按查询字符串参数区分缓存,不会出现不同参数返回相同缓存结果的问题

不要尝试在类库中强制注册响应缓存中间件,中间件执行顺序由消费端的请求管道配置决定,强制注入很容易导致中间件顺序异常,破坏消费端的原有业务逻辑。


内容的提问来源于stack exchange,提问作者Ted Nyberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:12:22