.NET Core 3.1 在命中中间件之前记录控制器中抛出的异常

Sze*_*eki 5 c# logging middleware exception .net-core

我向我的 中添加了一个异常处理中间件.net core 3.1 api,但它的行为不符合预期。我看到大量未处理异常的日志消息。

我做了一个简单的骨架来重现它。我没有配置日志记录,但行为是相同的。

启动.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.ConfigureExceptionHandler();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}
Run Code Online (Sandbox Code Playgroud)

ExceptionHandlerMiddleware.cs

public static class ExceptionHandlerMiddleware
{
    public static void ConfigureExceptionHandler(this IApplicationBuilder app)
    {
        app.UseExceptionHandler(applicationBuilder =>
        {
            applicationBuilder.Run(async httpContext => await ExceptionHandlerAsync(httpContext));
        });
    }

    private static async Task ExceptionHandlerAsync(HttpContext context)
    {
        var contextFeature = context.Features.Get<IExceptionHandlerFeature>();

        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        var message = contextFeature?.Error.Message ?? "Internal Server Error with no inner exception";

        await context.Response.WriteAsync(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

异常控制器.cs

[ApiController]
[Route("api/[controller]")]    
public class ExceptionController : ControllerBase
{
    [Route("throw")]
    public IActionResult ThrowInController()
    {
        throw new Exception("Thrown in Controller");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以如果我调试通过的话,流程如下:

  • 点击http://localhost:53636/api/exception/throw
  • 命中断点ExceptionController(在throw ...命令上,此时控制台输出(或日志,如果配置)为空)
  • 异常被抛出ExceptionController
  • Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware: Error: An unhandled exception has occurred while executing the request.写入控制台输出(或记录)
  • 断点 inExceptionHandlerMiddleware被击中(在 上var contextFeature = ...;,因此是处理程序的第一行)
  • 执行异常处理逻辑
  • 返回api响应

我的问题是流程到达中间件并处理异常之前的中间“未处理”异常消息。在我的真实应用程序中,还有根据异常的元数据记录为警告或信息(而不是错误)的逻辑。但目前每个异常都会被记录多次。首先是错误(未处理的异常),其次是具有适当日志级别的中间件。

关于我做错了什么有什么建议吗?

更新

我找到了一个解决方法。如果我使用app.UseMiddleware<ExceptionHandlerMiddleware>();而不是app.UseExceptionHandler(...),我将不再收到有关未处理异常的消息。

ExceptionHandlerMiddleware.cs

public class ExceptionHandlerMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionHandlerMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception exception)
        {
            // handle exception, log it with the proper level, generate response, etc
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我仍然有兴趣知道为什么

Art*_*tur 1

这是因为这条线而发生的

_logger.UnhandledException(edi.SourceException);
Run Code Online (Sandbox Code Playgroud)

在运行处理程序之前,会将ExceptionHandlerMiddleware异常记录为错误。

我通过禁用来自 的所有日志解决了这个问题Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware。如果这个解决方案对您来说足够好,只需将此类别日志记录级别设置为None

"Logging": {
    "LogLevel": {
    "Default": "Information",
    "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "None"
  }
}
Run Code Online (Sandbox Code Playgroud)