ASP.Net web api: logging middleware: System.ObjectDisposedException: Cannot access a closed Stream

Viewed 788

I am trying to implement request-response logging middleware in asp.net core web API application. It's working as fine in normal flow. But on an exception in the application, seeing ObjectDisposed error

System.ObjectDisposedException: Cannot access a closed Stream.
Here are the code blocks:

public class LoggingMiddleware
{
        private readonly RequestDelegate _next;
        private readonly ILogger<RequestResponseLoggingMiddlewarecs> _logger;

        public LoggingMiddleware(RequestDelegate requestDelegate, ILogger<LoggingMiddleware> logger)
        {
            _next = requestDelegate;
            _logger = logger;
        }
        public async Task Invoke(HttpContext httpContext)
        {
            httpContext.Request.EnableBuffering();
            var body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
            _logger.LogInformation($"Body: {body}");
            httpContext.Request.Body.Position = 0;
            //await _next(context);
            var originalBodyStream = httpContext.Response.Body;
            using (var responseBody = new MemoryStream())
            {
                var response = httpContext.Response;

                response.Body = responseBody;
                
                await _next(httpContext);                

                string responseBodyContent = null;
                responseBodyContent = await ReadResponseBody(response);
                await responseBody.CopyToAsync(originalBodyStream);
                _logger.LogInformation(responseBodyContent);
            }
        } 
}  

In Startup.cs Configiration method

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{            
            if (env.IsDevelopment())
            {                
                app.UseExceptionHandler("/error-developer");                
            }
            else
            {
                app.UseExceptionHandler("/Error");               
                app.UseHsts();
            }
            app.UseHttpsRedirection();

            app.UseStaticFiles();
            
            app.UseMiddleware<RequestResponseLoggingMiddlewarecs>();

            if (!env.IsDevelopment())
            {
                app.UseSpaStaticFiles();
            }

            app.UseRouting();
}  

Error Controller

public class ErrorController : ControllerBase
{
        [Route("/error-developer")]
        public IActionResult Error([FromServices] IWebHostEnvironment webHostEnvironment)
        {
            var context = HttpContext.Features.Get<IExceptionHandlerFeature>();
            var ex = context?.Error;
            var isDev = webHostEnvironment.IsDevelopment();

            return Problem(
                detail: context.Error.StackTrace,
                title: context.Error.Message);
        }

        [Route("/error")]
        public IActionResult Error() => Problem();
}  

Exception throwing at await responseBody.CopyToAsync(originalBodyStream);

Any thoughts/ideas, please?
Or any better way of implementing request-response logging and exception handling?

0 Answers
Related