. NET Исключение Core 3.1, созданное в контроллере, регистрируется до попадания в промежуточное ПО - PullRequest
2 голосов
/ 26 мая 2020

Я добавил промежуточное ПО обработки исключений в свой .net core 3.1 api, но оно работает не так, как ожидалось. Я вижу множество сообщений журнала о необработанных исключениях.

Я сделал простой скелет для его воспроизведения. У меня не настроено ведение журнала, но поведение такое же.

Startup.cs

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

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

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);
    }
}

ExceptionController.cs

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

Итак, если я отлаживаю его, поток будет следующим:

  • hit http://localhost: 53636 / api / exception / throw
  • точка останова в ExceptionController достигнута (в команде throw ... в этот момент вывод консоли (или журнал, если настроен) пуст)
  • исключение выбрасывается в ExceptionController
  • Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware: Error: An unhandled exception has occurred while executing the request. записывается в вывод консоли (или регистрируется)
  • точка останова в ExceptionHandlerMiddleware достигнута (на var contextFeature = ...;, поэтому первая строка обработчика)
  • logi обработчика исключений c выполняется
  • возвращается ответ api

Моя проблема - это промежуточное «необработанное» сообщение об исключении до того, как поток попадет в промежуточное ПО и исключение будет обработано. В моем реальном приложении также есть logi c для регистрации как предупреждения или информации (а не как ошибки) в зависимости от метаданных исключения. Но в настоящее время каждое исключение регистрируется несколько раз. Во-первых, как ошибка (необработанное исключение), а во-вторых, промежуточным программным обеспечением с надлежащим уровнем журнала.

Есть предложения относительно того, что я делаю неправильно?

обновить

Я нашел обходной путь. Если я использую 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
        }
    }
}

Мне все равно было бы интересно узнать почему хотя

...