【问题标题】:UseExceptionHandling failing after stream.CopyToAsync() callStream.CopyToAsync() 调用后 UseExceptionHandling 失败
【发布时间】:2021-11-10 23:43:35
【问题描述】:

在将响应正文复制到流后,我在 .Net Core 3.1 WebApi 中遇到了 UseExceptionHandler 问题,开始无法触发。我正在使用中间件来拦截 webapi 项目的传入请求和传出响应,并将记录记录到表中。在调用 stream.CopyToAsync() 方法之前它工作正常。之后的任何异常都不会触发 ExceptionHandler,即使本地 try/catch 仍然会捕获异常并且在 catch 块中重新抛出异常仍然不会导致 ExceptionHandler 触发。

调用方法

 public async Task Invoke(HttpContext context)
        {   
               Stream originalBody = context.Response.Body;
                try
                {
                
                    using var memStream = new MemoryStream();
                    context.Response.Body = memStream;
                    await _next(context).ConfigureAwait(false);
                    await LogResponse(context, originalBody, memStream).ConfigureAwait(false);


                }
                catch (Exception ex)
                {
                    throw ex; 
                }
                finally
                {
                    context.Response.Body = originalBody;
                    originalBody.Close();                    
                }
            }
        }

日志响应方法

 private async Task LogResponse(HttpContext context, Stream originalBody, MemoryStream stream)
    {
        stream.Seek(0, SeekOrigin.Begin);
        string body = await new StreamReader(stream).ReadToEndAsync().ConfigureAwait(false);
        stream.Seek(0, SeekOrigin.Begin);
        
        //This is the line of code that breaks UseExceptionHandling pipeline
        await stream.CopyToAsync(originalBody).ConfigureAwait(false);

        var resp = new ApiLogItemRequest()
        {
            AppName = "AppName",
            CreatedBy = "AppName",
            DateTime = DateTime.Now,                
            RawBodyJson = body,
            TraceIdentifier = context.TraceIdentifier
        };

        await _logHelper.LogRawHttpBodyItem(resp);
    }

任何想法或提示将不胜感激。谢谢!

【问题讨论】:

    标签: .net asp.net-core exception asp.net-core-webapi middleware


    【解决方案1】:

    我能够找出问题所在。 originalBody 变量为空,然后ExceptionHandler 抛出异常,在中间件中创建了一个奇怪的错误循环,导致它无法执行处理程序的代码。我假设它与使用来自CopyToAsync() 代码行的空响应编写的上下文有关,但我不能 100% 确定原因。

    我更改了代码,以便它仅在 originalBody 不为空时确保复制,并解决了问题。

    我在调试控制台中认出了ExceptionHandler 挂断。 ExceptionMiddlewareInvoke 应该只被调用一次并完成,但紧随其后的是 HandleException 然后 Invoke 再次让我认为 ExceptionHandler 中有一些异常导致它跳过代码在那里。

    (我最初没有说明,但根本问题是 originalBody = context.Response.Body 是写在 之前 _next(context); 在这种情况下,没有要复制的响应正文。该逻辑应该发生在_next(context)之后

    System.Exception: Test exception
       at Project.Api.Middleware.ApiRequestResponseLog.Invoke(HttpContext context) in C:\GIT\Project\Project.Api\Middleware\ApiRequestResponseLog.cs:line 82
       at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
    //These below shouldn't have occured
       at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
       at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
       at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
    

    【讨论】:

      猜你喜欢
      • 2020-07-01
      • 2012-09-16
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多