ASP.NET Core 中间件开发:请求日志记录与异常统一处理
在 ASP.NET Core 中,中间件是处理 HTTP 请求和响应的核心组件。以下实现一个同时处理请求日志记录和全局异常捕获的中间件:
1. 创建中间件类
public class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GlobalExceptionMiddleware> _logger;
public GlobalExceptionMiddleware(
RequestDelegate next,
ILogger<GlobalExceptionMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var watch = Stopwatch.StartNew();
try
{
// 调用管道中的下一个中间件
await _next(context);
}
catch (Exception ex)
{
// 异常处理
await HandleExceptionAsync(context, ex);
}
finally
{
// 记录请求日志
watch.Stop();
LogRequest(context, watch.ElapsedMilliseconds);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
_logger.LogError(ex, "全局异常: {Message}", ex.Message);
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonSerializer.Serialize(new
{
Code = 500,
Message = "服务器内部错误",
Detail = ex.Message
}));
}
private void LogRequest(HttpContext context, long elapsedMs)
{
_logger.LogInformation(
"请求: {Method} {Path} | 响应: {StatusCode} | 耗时: {Elapsed}ms",
context.Request.Method,
context.Request.Path,
context.Response.StatusCode,
elapsedMs);
}
}
2. 注册中间件(Program.cs)
// 必须放在管道最前端以捕获所有异常
app.UseMiddleware<GlobalExceptionMiddleware>();
// 其他中间件注册
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
3. 关键设计说明
-
日志记录功能:
- 使用
Stopwatch精确计算请求处理时间 - 记录请求方法、路径、响应状态码和耗时
- 日志级别:Information(正常请求)/Error(异常请求)
- 使用
-
异常统一处理:
- 捕获所有未处理异常
- 返回标准化 JSON 错误响应:
{ "Code": 500, "Message": "服务器内部错误", "Detail": "具体错误信息" } - 自动记录异常堆栈(LogError)
-
性能优化点:
- 使用异步方法避免阻塞
- 异常处理中复用 HTTP 上下文对象
- 内置依赖注入支持(通过构造函数注入 ILogger)
4. 扩展建议
- 自定义异常处理:
// 在 HandleExceptionAsync 中添加
switch (ex)
{
case UnauthorizedAccessException:
context.Response.StatusCode = 401;
break;
case ValidationException:
context.Response.StatusCode = 400;
break;
}
- 敏感信息过滤:
// 生产环境隐藏异常详情
if (!app.Environment.IsDevelopment())
{
await context.Response.WriteAsync(JsonSerializer.Serialize(new
{
Code = 500,
Message = "服务器内部错误"
}));
}
5. 工作流程
graph TD
A[请求进入] --> B[开始计时]
B --> C{执行后续中间件}
C -->|成功| D[记录请求日志]
C -->|异常| E[记录异常并生成响应]
E --> D
D --> F[返回响应]
此实现满足以下要求:
- 统一处理所有未捕获异常
- 自动记录请求关键指标
- 返回标准化错误格式
- 支持灵活的日志配置
- 确保异常不会导致服务崩溃
注意:中间件注册顺序至关重要,必须置于管道最前端才能捕获后续中间件的所有异常。
1253

被折叠的 条评论
为什么被折叠?



