ASP.NET Core 7 开始内置了 Output Caching(输出缓存),替代了旧版的
[ResponseCache]和
IMemoryCache手动缓存响应体的方式,支持更细粒度、可策略化、可共享的 HTTP 级别响应缓存。它基于中间件实现,不依赖控制器或视图,适用于 MVC、Razor Pages、Minimal API 等所有 HTTP 终结点。
启用 Output Caching 中间件
在
Program.cs中注册并启用缓存服务和中间件: 调用
builder.Services.AddOutputCaching()添加服务(支持自定义缓存提供者,如内存、分布式) 在
app.UseOutputCaching()添加中间件,必须放在
UseRouting之后、
UseEndpoints或
Map之前
示例:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddOutputCaching(); // 默认使用内存缓存 var app = builder.Build(); app.UseRouting(); app.UseOutputCaching(); // ⚠️ 位置很重要 app.MapControllers(); app.Run();
为 Minimal API 或控制器配置缓存策略
有两种主流方式:声明式(特性)和代码式(委托)。推荐优先使用特性,简洁清晰。
控制器/Action 上加[OutputCache]:最常用,支持
Duration、
PolicyName、
VaryByQueryKeys、
VaryByHeader等参数 Minimal API 使用
WithMetadata<outputcacheattribute>()</outputcacheattribute>:例如
app.MapGet("/api/data", () => "hello").WithMetadata(new OutputCacheAttribute { Duration = 60 });
全局策略注册:在 AddOutputCaching()时通过
.AddPolicy("my-policy", builder => ...) 预定义策略,再用 [OutputCache(PolicyName = "my-policy")]复用
常见缓存控制场景与写法
输出缓存会自动设置
Cache-Control响应头,并根据策略决定是否复用响应。注意以下高频需求写法: 缓存 10 分钟:
[OutputCache(Duration = 600)]按查询参数区分缓存(如分页):
[OutputCache(VaryByQueryKeys = new[] { "page", "size" })]
按请求头区分(如 Accept-Language):[OutputCache(VaryByHeader = "Accept-Language")]禁用缓存(绕过):
[OutputCache(NoStore = true, Duration = 0)](仍会走中间件,但不存储) 仅对匿名用户缓存:需结合
VaryByCustom或自定义
IOutputCachePolicy判断
HttpContext.User.Identity.IsAuthenticated
调试与验证缓存是否生效
最直接方式是查看响应头:
命中缓存时,响应含X-Output-Cache: Hit(开发环境默认开启该标头) 未命中或跳过时,可能是策略不匹配、请求方法非 GET/HEAD、状态码非 2xx/304、或有
Set-Cookie等禁止缓存的响应头 开发时可启用日志:
builder.Logging.AddConsole().AddFilter("Microsoft.AspNetCore.OutputCaching", LogLevel.Debug);
注意:本地开发默认使用内存缓存,无持久性;生产建议搭配 Redis(需引用
Microsoft.Extensions.Caching.StackExchangeRedis并注册
AddStackExchangeRedisOutputCaching)。
基本上就这些。Output Caching 设计轻量、语义明确,比手动管理
IMemoryCache更安全,也比旧
[ResponseCache]更灵活。关键是理解「策略驱动」和「Vary 机制」——缓存不是简单存 Response.Body,而是按一组维度键(key)来索引和匹配。
