2
votes

I have the following code in a class that implements IAsyncActionFilter using .Net Core.

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

This line:

using (var reader = new StreamReader(context.HttpContext.Response.Body))

produces the following error

fail: Microsoft.AspNetCore.Server.Kestrel[13]

Connection id "0HLFBE2K7NSD3", Request id "0HLFBE2K7NSD3:00000001": An unhandled exception was thrown by the application. System.ArgumentException: Stream was not readable. at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen) at System.IO.StreamReader..ctor(Stream stream) at Adapter.Logging.Middleware.LogResponseFilter.d__2.MoveNext() in C:\src\Adapter\Logging\Middleware\LogRequestResponseFilter.cs:line 56

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__10.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1.d__2.MoveNext()

My question is:

What do I need to do in order to safely reset the response stream?

I have another implementation of IAsyncActionFilter for logging:

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
You should make your post more detailed and reformat the error message.0xCursor
Maybe try Result filters instead.Mark G

1 Answers

0
votes

Probably put "await next.Invoke();" at the end of the method.