在ASP.NET Core应用开发中,全局异常处理能够统一捕获应用运行时产生的所有未处理异常,避免异常信息直接暴露给前端用户,同时可以集中记录异常日志、返回统一的错误响应格式,是后端开发必备的基础能力。C#实现全局异常处理最常用的方式就是自定义异常中间件,通过中间件管道统一拦截异常。

为什么需要全局异常处理
如果没有全局异常处理,当应用出现未捕获的异常时,ASP.NET Core会返回默认的500错误页面,这种页面不仅用户体验差,还可能泄露敏感的服务端信息。全局异常处理可以解决以下问题:
- 统一异常响应格式,让前端可以稳定解析错误信息
- 避免异常堆栈信息直接暴露,提升应用安全性
- 集中记录异常日志,方便后续排查问题
- 减少重复的try-catch代码,让业务代码更简洁
自定义异常中间件实现步骤
1. 创建异常中间件类
首先我们需要创建一个实现IMiddleware接口的中间件类,或者在请求委托中直接编写异常处理逻辑。以下是自定义异常中间件的完整实现:
using Microsoft.AspNetCore.Http;
using System;
using System.Text.Json;
using System.Threading.Tasks;
namespace Demo.Middlewares
{
/// <summary>
/// 全局异常中间件
/// </summary>
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, "应用发生未处理异常");
// 处理异常并返回响应
await HandleExceptionAsync(context, ex);
}
}
/// <summary>
/// 处理异常并返回统一响应
/// </summary>
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
// 设置响应状态码和类型
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json;charset=utf-8";
// 构造统一错误响应对象
var response = new
{
Code = 500,
Message = "服务内部异常,请稍后重试",
// 开发环境可以返回详细错误信息,生产环境建议关闭
Detail = exception.Message
};
// 序列化响应对象并返回
var jsonResponse = JsonSerializer.Serialize(response);
await context.Response.WriteAsync(jsonResponse);
}
}
}
2. 注册异常中间件
中间件创建完成后,需要在Program.cs中注册该中间件,注意中间件的注册顺序很重要,全局异常中间件需要放在所有可能出现异常的中间件之前,通常放在最前面:
using Demo.Middlewares; var builder = WebApplication.CreateBuilder(args); // 添加服务配置 builder.Services.AddControllers(); var app = builder.Build(); // 注册全局异常中间件,放在最前面 app.UseMiddleware<GlobalExceptionMiddleware>(); // 其他中间件配置 app.UseAuthorization(); app.MapControllers(); app.Run();
扩展:区分不同异常类型处理
实际开发中我们可能需要针对不同的异常类型返回不同的状态码和错误信息,比如业务异常返回400,权限异常返回403,我们可以修改HandleExceptionAsync方法实现这个需求:
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
// 默认状态码
int statusCode = 500;
string message = "服务内部异常,请稍后重试";
// 根据异常类型设置不同的状态码和消息
switch (exception)
{
case ArgumentException:
statusCode = 400;
message = "请求参数错误";
break;
case UnauthorizedAccessException:
statusCode = 403;
message = "无权限访问该资源";
break;
case FileNotFoundException:
statusCode = 404;
message = "请求的资源不存在";
break;
}
context.Response.StatusCode = statusCode;
context.Response.ContentType = "application/json;charset=utf-8";
var response = new
{
Code = statusCode,
Message = message,
Detail = exception.Message
};
var jsonResponse = JsonSerializer.Serialize(response);
await context.Response.WriteAsync(jsonResponse);
}
注意事项
- 异常中间件不要捕获所有异常后不做任何处理,至少要记录异常日志,否则排查问题会非常困难
- 生产环境建议不要返回详细的异常堆栈信息给前端,避免泄露服务端敏感信息
- 如果应用中使用了其他异常处理组件,比如健康检查、开发者异常页面,要注意注册顺序,避免冲突
- 异步方法中抛出的异常也可以被该中间件正常捕获,不需要额外处理
C#ASP.NET_Core全局异常处理异常中间件修改时间:2026-07-11 19:48:22