UseExceptionHandler是ASP.NET Core中处理HTTP请求未捕获异常的标准中间件,需置于UseRouting之后、UseEndpoints之前,仅捕获请求生命周期内异常,不处理启动、后台任务及路由前异常。

ASP.NET Core 中用 UseExceptionHandler 捕获未处理异常
ASP.NET Core 不再支持传统的 Global.asax 或 Application_Error,全局异常必须在中间件管道中注册。最标准的做法是调用 UseExceptionHandler,它会拦截所有未被 try/catch 捕获的异常,并重定向到指定的错误处理路径(如 /error)或直接返回响应。
关键点:
-
UseExceptionHandler必须放在UseRouting之后、UseEndpoints之前,否则无法生效 - 它只捕获 HTTP 请求生命周期内的异常,不处理后台任务(如
HostedService)或应用启动阶段的异常 - 默认返回状态码 500,但响应体内容可自定义(JSON、HTML 或纯文本)
app.UseExceptionHandler("/error"); // 重定向到控制器路由
// 或
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
context.Response.ContentType = "application/json";
var ex = context.Features.Get()?.Error;
await context.Response.WriteAsJsonAsync(new { error = ex?.Message });
});
});
在 /error 控制器里获取原始异常信息
使用路径方式(如 /error)时,需确保对应控制器能从 IExceptionHandlerFeature 中提取异常详情。这个 Feature 只在 UseExceptionHandler("/error") 触发的请求中存在,普通请求里取不到。
常见疏漏:
- 忘记添加
[Route("error")]或路由匹配失败,导致进不了该 Action - 直接读
HttpContext.Request.Query或Body试图找异常 —— 错,必须用context.Features.Get() - 没检查
Feature?.Error是否为 null,导致空引用异常
[Route("error")]
public class ErrorController : ControllerBase
{
[HttpGet]
public IActionResult HandleError()
{
var feature = HttpContext.Features.Get();
var ex = feature?.Error;
if (ex == null) return Problem("Unknown error", statusCode: 500);
// 生产环境避免暴露堆栈,开发环境可加
var response = new { message = ex.Message, stack = Environment.IsDevelopment() ? ex.StackTrace : null };
return Problem(detail: ex.Message, statusCode: 500);
}
}
如何区分开发/生产环境并控制错误输出粒度
直接把 Exception.StackTrace 或 InnerException 返回给前端,在生产环境属于严重安全风险。ASP.NET Core 提供了 Environment.IsDevelopment() 和内置的 ProblemDetails 标准化结构,应配合使用。
建议做法:
- 开发环境:返回完整
StackTrace+InnerException,便于调试 - 生产环境:仅返回泛化错误消息(如 "An unexpected error occurred"),日志记录完整异常
- 避免在 JSON 响应中拼接
ex.ToString(),它包含敏感类型名和路径
日志记录必须独立做,不能依赖 UseExceptionHandler 的响应逻辑。推荐在 HandleError 方法开头就调用 _logger.LogError(ex, "Unhandled exception")。
全局异常处理不覆盖的三种典型场景
UseExceptionHandler 很强大,但不是万能的。以下三类异常它完全捕获不到,必须单独处理:
-
Startup.ConfigureServices阶段抛出的异常 —— 应用根本起不来,需靠宿主日志(如 Windows Event Log 或dotnet run控制台输出)排查 - 后台服务(
IHostedService)中未捕获的异常 —— 这些运行在独立线程,需在ExecuteAsync内自行try/catch并记录 - 终结点路由前的异常(如
UseHttpsRedirection中证书验证失败)—— 发生在中间件链更早位置,可能绕过UseExceptionHandler
尤其要注意 HTTPS 重定向失败时,浏览器可能直接显示“连接被重置”,而服务端日志里没有任何异常记录 —— 这类问题得查 Kestrel 日志级别或启用 Microsoft.AspNetCore.Server.Kestrel 的 Debug 级别日志。










