我在。net Core 3.1中遇到UseExceptionHandler的问题,WebApi开始在将响应体复制到流后无法触发。我正在使用中间件来拦截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();
}
}
}
LogResponse方法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);
}
任何想法或提示将不胜感激。谢谢!
我能找出问题所在。originalBody
变量为空,然后ExceptionHandler
抛出一个异常,在中间件中创建一个奇怪的错误循环,导致它无法执行处理程序的代码。我假设它与从CopyToAsync()
行代码中使用空响应编写的上下文有关,但我不能100%确定原因。
我更改了代码,使其仅在originalBody
不为空时进行复制,并且它修复了这个问题。
我在调试控制台中识别出ExceptionHandler
挂机。ExceptionMiddleware
的Invoke
只应该被调用一次,但随后是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:GITProjectProject.ApiMiddlewareApiRequestResponseLog.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()