在ASP.NET Core项目里,未处理的异常如果直接返回给客户端,不仅会暴露系统内部信息,还会造成非常差的用户体验。通过自定义全局异常中间件,可以统一捕获所有请求处理过程中抛出的异常,进行日志记录后返回统一的错误响应。

全局异常中间件的作用
全局异常中间件的核心作用是拦截请求管道中后续中间件和控制器抛出的未处理异常,避免异常向上传播导致程序崩溃。它主要能实现三个目标:
- 统一异常响应格式,让客户端接收到的错误信息结构一致
- 隐藏系统内部敏感信息,避免异常堆栈等细节暴露
- 集中记录异常日志,方便后续排查问题
创建全局异常中间件
首先我们需要创建一个自定义的中间件类,这个类需要包含请求委托和日志服务依赖。以下是中间件的完整实现代码:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Text.Json;
using System.Threading.Tasks;
namespace Demo.Middlewares
{
// 全局异常中间件类
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)
{
try
{
// 调用后续中间件和请求处理逻辑
await _next(context);
}
catch (Exception ex)
{
// 捕获异常后记录日志
_logger.LogError(ex, "请求处理过程中发生未处理异常,请求路径:{Path}", context.Request.Path);
// 处理异常并返回统一响应
await HandleExceptionAsync(context, ex);
}
}
// 处理异常并返回统一格式响应
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
// 设置响应内容类型和状态码
context.Response.ContentType = "application/json";
context.Response.StatusCode = 500;
// 构造统一的错误响应对象
var response = new
{
Code = 500,
Message = "服务器内部发生错误,请稍后重试",
// 开发环境可以返回异常信息,生产环境建议关闭
Detail = exception.Message
};
// 序列化响应对象并写入响应体
var jsonResponse = JsonSerializer.Serialize(response);
await context.Response.WriteAsync(jsonResponse);
}
}
}
注册全局异常中间件
中间件创建完成后,需要在程序启动时注册到请求管道中。注意中间件的注册顺序很重要,全局异常中间件需要放在所有可能出现异常的中间件之前,通常放在管道的最前面,除了少数不需要异常处理的组件比如HTTPS重定向中间件。
在Program.cs中添加以下注册代码:
var builder = WebApplication.CreateBuilder(args); // 添加控制器服务 builder.Services.AddControllers(); var app = builder.Build(); // 注册全局异常中间件,放在最前面确保能捕获所有后续中间件的异常 app.UseMiddleware<Demo.Middlewares.GlobalExceptionMiddleware>(); // 其他中间件注册 app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
自定义异常响应格式
实际项目中可能需要根据异常类型返回不同的状态码和错误信息,比如业务异常返回400状态码,权限异常返回403状态码。我们可以修改HandleExceptionAsync方法实现这个需求:
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
var response = new
{
Code = 500,
Message = "服务器内部发生错误,请稍后重试",
Detail = exception.Message
};
// 根据异常类型设置不同的状态码和提示信息
if (exception is ArgumentException)
{
context.Response.StatusCode = 400;
response = new
{
Code = 400,
Message = "请求参数错误",
Detail = exception.Message
};
}
else if (exception is UnauthorizedAccessException)
{
context.Response.StatusCode = 403;
response = new
{
Code = 403,
Message = "无权限访问该资源",
Detail = exception.Message
};
}
else
{
context.Response.StatusCode = 500;
}
var jsonResponse = JsonSerializer.Serialize(response);
await context.Response.WriteAsync(jsonResponse);
}
注意事项
在使用全局异常中间件时需要注意以下几点:
- 不要在中间件中捕获异常后不做任何处理,至少要记录日志,否则异常会被静默吞掉,难以排查问题
- 生产环境不要将异常的详细堆栈信息返回给客户端,避免暴露系统内部结构
- 如果项目中同时使用了ASP.NET Core自带的异常处理中间件UseExceptionHandler,不要重复注册,两者功能重叠,选择一种即可
- 中间件中不要抛出新的未处理异常,否则会导致请求管道崩溃
总结
通过自定义中间件实现ASP.NET Core全局异常处理,能够统一管控所有请求的异常情况,减少重复的异常捕获代码,提升项目的可维护性。开发者可以根据自身项目的需求,扩展中间件的异常处理逻辑,比如添加异常分类、对接监控系统、返回更丰富的错误信息等,让异常处理机制更贴合项目的实际场景。
ASP.NET_Core全局异常处理中间件异常捕获修改时间:2026-07-21 19:39:26