0Pricing
C# Academy · 课时

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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 创建第一个 Minimal API
  2. 路由组、参数与验证
  3. Minimal API 中间件与筛选器
  4. OpenAPI、版本控制与部署
← 返回 C# Academy