在中间件中获取异常
Get exception in Middleware
我想创建一个 AspNetCore 中间件(旧 IHttpModule),它应该捕获异常(稍后保存它们或类似的东西)
然而,我不知道如何捕获中间件中的异常,尽管 HttpStatusCode 是 500
这是我的:
// Middleware
internal class ExceptionMiddleware
{
private readonly RequestDelegate _next;
public ExceptionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
// never gets here
}
// 500
HttpStatusCode statusCode = (HttpStatusCode)context.Response.StatusCode;
// how to get error message?
}
}
// Middleware Extension method
public static class ExceptionMiddlewareExtensions
{
public static IApplicationBuilder UseExceptionMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ExceptionMiddleware>();
}
}
// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseExceptionMiddleware();
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
我是这样触发异常的:
public IActionResult Index()
{
var test = 0;
var a = 100 / test;
return View();
}
您在中间件中正确使用了 try-catch
。
但是你的问题是你还注册了ExceptionHandler middleware (app.UseExceptionHandler
)。此中间件捕获所有未处理的异常并设置 500 状态代码(如果可以处理)。
作为一种可能的解决方案,请考虑交换中间件的顺序,这样您的中间件将是第一个捕获管道中进一步发生的异常的中间件:
app.UseExceptionHandler("/Home/Error");
app.UseExceptionMiddleware();
您正在重新发明轮子。
如何在没有自己的中间件的情况下正确完成:
您可以使用内置 ExceptionHandlerMiddleware
(app.UseExceptionHandler
) ASP.NET Core 为您获取错误详细信息,这没有记录但应该记录。
因此您可以通过 HttpContext.Features
:
访问您的异常详细信息
假设您在 /Home/Error
控制器的操作中调用它,您可以像这样访问它:
var exHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
var exception = exHandlerFeature.Error;
Also see this answer and question about Request Features
我想创建一个 AspNetCore 中间件(旧 IHttpModule),它应该捕获异常(稍后保存它们或类似的东西)
然而,我不知道如何捕获中间件中的异常,尽管 HttpStatusCode 是 500
这是我的:
// Middleware
internal class ExceptionMiddleware
{
private readonly RequestDelegate _next;
public ExceptionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
// never gets here
}
// 500
HttpStatusCode statusCode = (HttpStatusCode)context.Response.StatusCode;
// how to get error message?
}
}
// Middleware Extension method
public static class ExceptionMiddlewareExtensions
{
public static IApplicationBuilder UseExceptionMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ExceptionMiddleware>();
}
}
// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseExceptionMiddleware();
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
我是这样触发异常的:
public IActionResult Index()
{
var test = 0;
var a = 100 / test;
return View();
}
您在中间件中正确使用了 try-catch
。
但是你的问题是你还注册了ExceptionHandler middleware (app.UseExceptionHandler
)。此中间件捕获所有未处理的异常并设置 500 状态代码(如果可以处理)。
作为一种可能的解决方案,请考虑交换中间件的顺序,这样您的中间件将是第一个捕获管道中进一步发生的异常的中间件:
app.UseExceptionHandler("/Home/Error");
app.UseExceptionMiddleware();
您正在重新发明轮子。
如何在没有自己的中间件的情况下正确完成:
您可以使用内置 ExceptionHandlerMiddleware
(app.UseExceptionHandler
) ASP.NET Core 为您获取错误详细信息,这没有记录但应该记录。
因此您可以通过 HttpContext.Features
:
假设您在 /Home/Error
控制器的操作中调用它,您可以像这样访问它:
var exHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
var exception = exHandlerFeature.Error;
Also see this answer and question about Request Features