Сетевой обработчик исключений ядра лямбда создает дубликаты - PullRequest
3 голосов
/ 03 мая 2019

Я использую лямбда-функцию для метода UseExceptionHandler и .net core 2.2:

public static class ExceptionMiddlewareExtensions
{
    public static void ConfigureExceptionHandler(this IApplicationBuilder app, ILogger logger)
    {
        app.UseExceptionHandler(builder =>
        {
            builder.Run(async context =>
            {
                context.Response.ContentType = "application/json";
                var feature = context.Features.Get<IExceptionHandlerPathFeature>();
                var exception = feature.Error;

                var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
                if (contextFeature != null)
                {
                    LogError(contextFeature, logger);
                    await ForwardError(context, exception);
                }
            });
        });
    }

    private static void LogError(IExceptionHandlerFeature contextFeature, ILogger logger)
    {
        logger.LogError($"{contextFeature.Error}");
    }

    private static async Task ForwardError(HttpContext context, Exception exception)
    {
        var httpStatusCodeException = exception as HttpException;
        if (exception is HttpException)
        {
            context.Response.StatusCode = (int)httpStatusCodeException.StatusCode;
            await context.Response.WriteAsync(new ErrorDetails()
            {
                Date = DateTime.UtcNow,
                Version = "v1",
                Code = httpStatusCodeException.Code,
                Type = httpStatusCodeException.Type.ToString(),
                Message = httpStatusCodeException.Message
            }.ToString());
        }
        else
        {
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            await context.Response.WriteAsync(new ErrorDetails()
            {
                Date = DateTime.UtcNow,
                Version = "v1",
                Code = Code.InternalServerError,
                Type = Exceptions.Type.InvalidParameter.ToString(),
                Message = "Internal Server Error."
            }.ToString());
        }
    }
}

}

Теперь я регистрирую обработчик исключений в файле startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseStatusCodePages();
    app.ConfigureExceptionHandler(logger);
    app.UseMiddleware<ProxyMiddleware>();
}

Теперь, если выбрасывать исключение в proxymiddleware в методе invoke, исключение регистрируется дважды, что я делаю неправильно? Я хочу зарегистрировать исключение только один раз.

ProxyMiddleware:

public class ProxyMiddleware
{
    private readonly RequestDelegate next;

    public ProxyMiddleware(RequestDelegate next)
    {
        if (next == null)
        {
            throw new ArgumentNullException(nameof(next));
        }

        this.next = next;
    }

    public Task Invoke(HttpContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        throw new ArgumentNullException("Test");
    }
}

Это журналы исключений из консоли, которые я получаю из промежуточного программного обеспечения:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://127.0.0.1:4000/test
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
      An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: Test
   at TestProject.ProxyMiddleware.Invoke(HttpContext context) in C:\TestProject\ProxyMiddleware.cs:line 29
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
fail: TestProject.Startup[0]
      System.ArgumentNullException: Value cannot be null.
      Parameter name: Test
         at TestProject.ProxyMiddleware.Invoke(HttpContext context) in C:\TestProject\ProxyMiddleware.cs:line 29
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 4681.7259ms 500 application/json
...