bit
bit

Reputation: 4487

Web API Core 3.1 ExceptionHandler middleware throws 'cannot write to closed stream' while writing to HttpContext.Response

I have a simple Web API Core v3.1 where I am trying to handle Exceptions Globally. After following this answer https://stackoverflow.com/a/55166404/1508398, here is my code for doing that.

 app.UseExceptionHandler(appBuilder => appBuilder.Run(async context =>
 {
     var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
     var exception = exceptionHandlerPathFeature.Error;

     var result = JsonConvert.SerializeObject(new { error = exception.Message });
     context.Response.ContentType = "application/json";
     await context.Response.WriteAsync(result);
 }));

The error I get is at context.Response.WriteAsync(result); is :

System.ObjectDisposedException: Cannot access a closed Stream.

I am pretty sure I am missing something basic but unable to figure this out.

I essentially need to wrap the response into an object whenever an exception occurrs.

Upvotes: 6

Views: 2979

Answers (1)

Athanasios Kataras
Athanasios Kataras

Reputation: 26342

It looks like someone else (another middleware) has already closed the stream.

In .net-core the ordering matters. Remember in the link you shared:

Important: Remember to add it before UseMvc (or UseRouting in .Net Core 3) as order is important.

So declare the UseExceptionHandler before any other Middleware and or configuration declaration.

Check the middleware guide here

Chain multiple request delegates together with Use. The next parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by not calling the next parameter. You can typically perform actions both before and after the next delegate, as the following example demonstrates:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

UseExceptionHandler is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls.

The first run, terminates the pipeline. So you can do some work, but in the end when the first run occurs the Response will close.

Please share more code for us to help more.

Upvotes: 2

Related Questions