Minimal API 中间件与筛选器
向 Minimal API 管道添加身份验证、授权、异常处理和端点筛选器。
Minimal API 中间件与筛选器 是 CoddyKit 上的免费 C# Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
中间件与端点筛选器的区别
ASP.NET Core 有两个扩展层:中间件(包装整个管道,对每个请求运行)和端点筛选器(仅对特定端点运行)。两者都适用于最小 API。
向最小 API 添加中间件
使用 app.Use* 方法添加标准 ASP.NET Core 中间件。顺序很重要——中间件会按照注册顺序运行。
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();
app.MapGet("/secure", () => "Protected endpoint")
.RequireAuthorization();
app.Run();内联端点筛选器
端点筛选器类似于作用域限定在单个端点上的中间件。使用 AddEndpointFilter 内联添加筛选器。筛选器可以在不调用 next 的情况下返回结果,从而提前终止请求。
app.MapGet("/guarded", () => "Secret data")
.AddEndpointFilter(async (ctx, next) =>
{
var header = ctx.HttpContext.Request.Headers["X-Api-Key"];
if (header != "my-secret-key")
return Results.Unauthorized();
return await next(ctx); // proceed to handler
});基于类的端点筛选器
实现 IEndpointFilter 即可创建可复用的筛选器。它们可以应用于单个端点或整个路由组。
public class LoggingFilter : IEndpointFilter
{
private readonly ILogger<LoggingFilter> _logger;
public LoggingFilter(ILogger<LoggingFilter> logger) => _logger = logger;
public async ValueTask<object?> InvokeAsync(
EndpointFilterInvocationContext ctx,
EndpointFilterDelegate next)
{
_logger.LogInformation("Before: {Path}", ctx.HttpContext.Request.Path);
var result = await next(ctx);
_logger.LogInformation("After: {Path}", ctx.HttpContext.Request.Path);
return result;
}
}
// Apply to a group
app.MapGroup("/api").AddEndpointFilter<LoggingFilter>();异常处理中间件
使用 app.UseExceptionHandler 或内置的 ProblemDetails 中间件捕获未处理的异常,并返回 RFC 7807 问题响应。
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
// OR for custom logic:
app.UseExceptionHandler(errApp =>
errApp.Run(async ctx =>
{
var ex = ctx.Features.Get<IExceptionHandlerFeature>()?.Error;
ctx.Response.StatusCode = 500;
await ctx.Response.WriteAsJsonAsync(new { error = ex?.Message });
}));短路中间件
使用 app.MapShortCircuit()(.NET 8+),或在筛选器中使用 Results.StatusCode(),即可立即返回响应,而无需运行完整管道。
// Block known bad bots at the edge
app.MapGet("/robots.txt", () => "User-agent: *\nDisallow: /")
.ShortCircuit(); // .NET 8: returns response immediately
// Or in a filter:
app.MapGet("/maintenance", () => "OK")
.AddEndpointFilter((ctx, next) =>
ValueTask.FromResult<object?>(Results.StatusCode(503)));.NET 7+ 中的速率限制
内置的速率限制中间件可以保护端点免遭滥用。使用 RequireRateLimiting() 全局应用策略,或将策略应用于单个端点。
using System.Threading.RateLimiting;
builder.Services.AddRateLimiter(opt =>
{
opt.AddFixedWindowLimiter("fixed", o =>
{
o.PermitLimit = 10;
o.Window = TimeSpan.FromSeconds(10);
o.QueueLimit = 0;
o.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});
opt.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});
app.UseRateLimiter();
app.MapGet("/search", Search).RequireRateLimiting("fixed");CORS 配置
在服务中配置 CORS 策略,并全局应用或按端点应用这些策略,以控制哪些源可以访问您的 API。
builder.Services.AddCors(opt =>
opt.AddPolicy("AllowFrontend", policy =>
policy.WithOrigins("https://myapp.com")
.AllowAnyHeader()
.AllowAnyMethod()));
app.UseCors("AllowFrontend");
// Or per endpoint:
app.MapGet("/public-data", () => "data")
.RequireCors("AllowFrontend");输出缓存中间件
AddOutputCache 会在服务器端缓存响应。将其应用于特定端点,即可提供缓存的响应,而不必在每个请求中都访问数据库。
builder.Services.AddOutputCache();
app.UseOutputCache();
app.MapGet("/products", async (AppDbContext db) =>
Results.Ok(await db.Products.AsNoTracking().ToListAsync()))
.CacheOutput(p => p.Expire(TimeSpan.FromMinutes(5)));筛选器顺序与链接
筛选器会按照添加顺序执行(最外层先执行,最内层后执行,类似于中间件)。您可以在同一个端点或组上链接多个筛选器。
app.MapPost("/orders", CreateOrder)
.AddEndpointFilter<LoggingFilter>() // runs first
.AddEndpointFilter<ValidationFilter>() // runs second
.AddEndpointFilter<AuthFilter>() // runs third
.RequireAuthorization(); // JWT checked by middleware真实案例:API 密钥中间件
一个可复用的 API 密钥中间件,从标头读取密钥;如果密钥无效,则直接返回 401。
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private readonly string _expectedKey;
public ApiKeyMiddleware(RequestDelegate next, IConfiguration cfg)
{
_next = next;
_expectedKey = cfg["ApiKey"] ?? throw new Exception("ApiKey not configured");
}
public async Task InvokeAsync(HttpContext ctx)
{
if (!ctx.Request.Headers.TryGetValue("X-Api-Key", out var key)
|| key != _expectedKey)
{
ctx.Response.StatusCode = 401;
await ctx.Response.WriteAsync("Invalid API key");
return;
}
await _next(ctx);
}
}
app.UseMiddleware<ApiKeyMiddleware>();快速检查
在最小 API 中,中间件与端点筛选器之间的关键区别是什么?
回顾:中间件与筛选器
要点:
- 中间件(UseX)按照管道顺序全局运行,处理每个请求
- 端点筛选器(AddEndpointFilter)的作用域限定在特定端点或组
- 实现 IEndpointFilter,创建可复用且便于使用 DI 的筛选器类
- 内置中间件包括:速率限制、CORS、输出缓存和异常处理
- 筛选器顺序很重要——它们像中间件一样嵌套(先添加的位于最外层)
常见问题解答
「Minimal API 中间件与筛选器」课时是免费的吗?
是的 — 「Minimal API 中间件与筛选器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「Minimal API 中间件与筛选器」这节课中我会学到什么?
向 Minimal API 管道添加身份验证、授权、异常处理和端点筛选器。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「Minimal API 中间件与筛选器」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 创建第一个 Minimal API
- 路由组、参数与验证
- Minimal API 中间件与筛选器
- OpenAPI、版本控制与部署