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