在动作过滤器中记录响应正文

时间:2018-07-16 23:13:30

标签: asp.net-mvc asp.net-core actionfilterattribute

我在使用.Net Core实现IAsyncActionFilter的类中具有以下代码。

public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
    await next.Invoke();

    using (var reader = new StreamReader(context.HttpContext.Response.Body))
    {
        var responseBodyText = await reader.ReadToEndAsync();

        var messageObjToLog = new
        {
            responseBody = responseBodyText,
            statusCode = context.HttpContext.Response.StatusCode
        };
        _logger.LogInformation(JsonConvert.SerializeObject(messageObjToLog));
        context.HttpContext.Response.Body.Seek(0, SeekOrigin.Begin);
    }
}

此行:

“使用(var reader = new StreamReader(context.HttpContext.Response.Body))”

产生以下错误

  

失败:Microsoft.AspNetCore.Server.Kestrel [13]

     

连接ID“ 0HLFBE2K7NSD3”,请求ID“ 0HLFBE2K7NSD3:00000001”:An   应用程序引发了未处理的异常。   System.ArgumentException:流不可读。在   System.IO.StreamReader..ctor(流流,编码编码,布尔   detectEncodingFromByteOrderMarks,Int32 bufferSize,布尔值LeaveOpen)   在System.IO.StreamReader..ctor(Stream stream)在   Adapter.Logging.Middleware.LogResponseFilter.d__2.MoveNext()   在C:\ src \ Adapter \ Logging \ Middleware \ LogRequestResponseFilter.cs:line中   56

     

---从上一个引发异常的位置开始的堆栈结束---   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__10.MoveNext()

     

---从上一个引发异常的位置开始的堆栈结束---   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext   上下文)   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State&   接下来,范围和作用域,对象和状态,布尔值和isCompleted)位于   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()

     

---从上一个引发异常的位置开始的堆栈结束---   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext()

     

---从上一个引发异常的位置开始的堆栈结束---   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext   上下文)   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State&next,   范围和范围,对象和状态,布尔值和完成)位于   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()

     

---从上一个引发异常的位置开始的堆栈结束---   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()

     

---从上一个引发异常的位置开始的堆栈结束---   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()

     

---从上一个引发异常的位置开始的堆栈结束---   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext()   ---从上一个引发异常的位置开始的堆栈跟踪-   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext()   ---从上一个引发异常的位置开始的堆栈跟踪-   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1.d__2.MoveNext()

我的问题是:

为了安全地重置响应流,我需要做什么?

我还有另一个用于记录日志的IAsyncActionFilter实现:

public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        using (var reader = new StreamReader(context.HttpContext.Request.Body))
        {
            var requestBodyText = await reader.ReadToEndAsync();
            context.HttpContext.Request.EnableRewind();
            context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
            var messageObjToLog = new
            {
                scheme = context.HttpContext.Request.Scheme,
                host = context.HttpContext.Request.Host,
                path = context.HttpContext.Request.Path,
                queryString = context.HttpContext.Request.Query,
                requestBody = requestBodyText
            };
            _logger.LogInformation(JsonConvert.SerializeObject(messageObjToLog));
        }

        await next.Invoke();
    }

1 个答案:

答案 0 :(得分:0)

可能将“ await next.Invoke();”在方法末尾。