在ASP.NET Core 中,请求通道(Request Pipeline)和中间件(Middleware)是处理 HTTP 请求的核心机制。理解它们的工作原理对于构建高效、可扩展的 Web 应用至关重要。
一、请求通道(Request Pipeline)
请求通道是ASP.NET Core 处理 HTTP 请求的核心概念,它是一个由多个中间件组件组成的管道。当客户端发送请求到服务器时,请求会依次通过这些中间件,每个中间件可以对请求进行处理、修改,然后将请求传递给下一个中间件。响应则沿着相反的方向返回给客户端。
关键特点:
- 顺序执行:中间件按照注册的顺序依次处理请求。
- 双向流动:请求和响应都要经过整个管道,但方向相反。
- 可终止性:任何中间件都可以终止请求处理并直接返回响应。
二、中间件(Middleware)
中间件是请求通道中的独立组件,负责执行特定的任务(如身份验证、日志记录、静态文件处理等)。每个中间件:
- 接收一个
HttpContext
对象(包含请求和响应信息)。 - 可以选择将请求传递给下一个中间件,或直接生成响应。
中间件的基本结构:
中间件通常是一个实现了RequestDelegate
委托的类,包含一个Invoke
或InvokeAsync
方法:
csharp
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next; // 指向下一个中间件
}
public async Task InvokeAsync(HttpContext context)
{
// 1. 请求处理逻辑(在调用下一个中间件之前)
Console.WriteLine("请求开始处理...");
// 2. 调用下一个中间件
await _next(context);
// 3. 响应处理逻辑(在后续中间件返回后)
Console.WriteLine("响应处理完成。");
}
}
三、常见内置中间件
ASP.NET Core 提供了多种内置中间件,常见的有:
-
静态文件中间件:处理静态文件请求(如 HTML、CSS、JavaScript)。
csharp
app.UseStaticFiles();
-
路由中间件:负责将请求映射到具体的端点(如控制器、最小 API)。
csharp
app.UseRouting();
-
认证中间件:处理身份验证和授权。
csharp
app.UseAuthentication(); app.UseAuthorization();
-
异常处理中间件:捕获并处理应用程序中的异常。
csharp
app.UseExceptionHandler("/Error");
-
CORS 中间件:配置跨域资源共享。
csharp
app.UseCors();
四、中间件的注册方式
在Program.cs
中,中间件通过以下方法注册到请求通道:
1. Use () 方法
注册一个通用中间件,可选择性地将请求传递给下一个中间件。
csharp
app.Use(async (context, next) =>
{
// 请求处理
await next(context); // 传递给下一个中间件
// 响应处理
});
2. Run () 方法
注册一个终端中间件,不将请求传递给下一个中间件(终止管道)。
csharp
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from terminal middleware!");
});
3. Map () 方法
基于路径分支注册中间件(仅当请求路径匹配时执行)。
csharp
app.Map("/api", api =>
{
api.Run(async context =>
{
await context.Response.WriteAsync("API endpoint");
});
});
4. MapWhen () 方法
基于条件(如请求头、查询参数)分支注册中间件。
csharp
app.MapWhen(context => context.Request.Query.ContainsKey("debug"), debug =>
{
debug.UseDeveloperExceptionPage();
});
五、中间件执行顺序示例
以下是一个典型的中间件注册顺序及其执行流程:
csharp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// 1. 异常处理中间件(最先注册)
app.UseExceptionHandler("/Error");
// 2. 静态文件中间件
app.UseStaticFiles();
// 3. 路由中间件
app.UseRouting();
// 4. 认证和授权中间件
app.UseAuthentication();
app.UseAuthorization();
// 5. 端点中间件(最后注册)
app.MapControllers(); // 或 app.MapGet(), app.MapPost(), 等
app.Run();
执行流程:
- 请求进入 → 异常处理中间件 → 静态文件中间件 → 路由中间件 → 认证中间件 → 授权中间件 → 端点中间件。
- 如果匹配到端点 → 执行端点逻辑 → 响应返回,依次经过之前的中间件(按相反顺序)。
- 如果未匹配到端点 → 可能由静态文件中间件处理(如果是静态文件请求),否则返回 404。
六、自定义中间件
你可以创建自己的中间件类,并通过扩展方法简化注册:
1. 创建中间件类
csharp
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
public RequestLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine($"请求: {context.Request.Method} {context.Request.Path}");
await _next(context);
Console.WriteLine($"响应状态码: {context.Response.StatusCode}");
}
}
2. 创建扩展方法
csharp
public static class RequestLoggingMiddlewareExtensions
{
public static IApplicationBuilder UseRequestLogging(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestLoggingMiddleware>();
}
}
3. 在 Program.cs 中注册
csharp
app.UseRequestLogging();
七、中间件 vs 过滤器(Filter)
中间件和过滤器都可以处理请求,但它们的应用场景不同:
- 中间件:作用于整个请求通道,适合全局关注点(如日志、异常处理)。
- 过滤器:作用于 MVC 或 Razor Pages 的特定环节(如动作执行前后、模型绑定)。
总结
请求通道和中间件是ASP.NET Core 的核心机制,理解它们的工作原理有助于:
- 优化应用性能(合理安排中间件顺序)。
- 实现全局功能(如认证、日志)。
- 构建可扩展的 Web 应用。
建议在Program.cs
中按以下顺序注册中间件:
- 异常处理 → 2. 静态文件 → 3. 路由 → 4. 认证 / 授权 → 5. 端点。