在中间件中获取异常

Cat*_*lin 3 exception-handling asp.net-core asp.net-core-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?}");
    });
}
Run Code Online (Sandbox Code Playgroud)

我触发这样的异常:

public IActionResult Index()
{
    var test = 0;
    var a = 100 / test;

    return View();
}
Run Code Online (Sandbox Code Playgroud)

Kon*_*rad 6

你在重新发明轮子。

如何在没有自己的中间件的情况下正确地做到这一点:

您可以使用内置ExceptionHandlerMiddleware( app.UseExceptionHandler) ASP.NET Core 提供的错误详细信息,这没有记录,但应该记录。

当异常发生时,这个中间件设置IExceptionHandlerFeature(发生异常)和IExceptionHandlerPathFeature(来自IExceptionHandlerFeature) on HttpContext

因此,您可以通过HttpContext.Features以下方式访问您的异常详细信息:

假设您在/Home/Error控制器的操作中调用它,您可以像这样访问它:

var exHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
var exception = exHandlerFeature.Error;
Run Code Online (Sandbox Code Playgroud)

另请参阅有关请求功能的答案和问题

如果您有兴趣,也有关于此的博客文章


Set*_*Set 5

try-catch在中间件中正确使用。

但是您的问题是您还注册了ExceptionHandler中间件app.UseExceptionHandler)。该中间件捕获所有未处理的异常,并设置500个状态代码(如果可以处理)。


作为一种可能的解决方案,考虑交换中间件的顺序,因此您的中间件将是第一个捕获进一步发生在管道中的异常的中间件:

app.UseExceptionHandler("/Home/Error");
app.UseExceptionMiddleware();
Run Code Online (Sandbox Code Playgroud)

  • @Catalin是的,原因是[DeveloperExceptionPageMiddleware](https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs)期望出现异常,而您的中间件会吞下它们。目前尚不清楚您到底想要实现什么,但是如果您只需要在中间件中记录异常,然后再使用ExceptionPages,则需要在中间件中重新抛出异常 (2认同)