Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set response status in ASP.NET core middleware

I have a middleware, which hides exception from client and returns 500 error in case of any exception:

public class ExceptionHandlingMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next.Invoke(context);
        }
        catch (Exception exception)
        {
            var message = "Exception during processing request";
            using (var writer = new StreamWriter(context.Response.Body))
            {
                context.Response.StatusCode = 500; //works as it should, response status 500
                await writer.WriteAsync(message);
                context.Response.StatusCode = 500; //response status 200
            }
        }
    }
}

My problem is that, if I set response status before writing body, client will see this status, but if I set status after writing message to body, client will receive response with status 200.

Could somebody explain me why it's happening?

P.S. I am using ASP.NET Core 1.1

like image 792
Uriil Avatar asked Jan 31 '17 20:01

Uriil


People also ask

What is exception handling middleware?

The exception handling middleware re-executes the request using the original HTTP method. If an error handler endpoint is restricted to a specific set of HTTP methods, it runs only for those HTTP methods. For example, an MVC controller action that uses the [HttpGet] attribute runs only for GET requests.

What is IApplicationBuilder in .NET Core?

UseExceptionHandler(IApplicationBuilder) Adds a middleware to the pipeline that will catch exceptions, log them, and re-execute the request in an alternate pipeline. The request will not be re-executed if the response has already started.

How does ASP.NET Core middleware work?

Middleware in ASP.NET Core controls how our application responds to HTTP requests. It can also control how our application looks when there is an error, and it is a key piece in how we authenticate and authorize a user to perform specific actions.

What is the difference between IApplicationBuilder use () and IApplicationBuilder run ()?

The Run method is an extension method on IApplicationBuilder and accepts a parameter of RequestDelegate. IApplicationBuilder. Use() method : Used to create a simple middleware which can be "chained" to other functions over the pipeline.


1 Answers

That's by design, when you know how HTTP works.

Headers are in the beginning of the datastream (see wiki example). Once you send the data, you can't change/modify the headers, because the data has already been sent over the wire.

You would have to buffer the whole response if you want to set it later on, but this increases the memory usage. Here is a sample on how to swap the stream for a memory stream.

like image 140
Tseng Avatar answered Sep 21 '22 12:09

Tseng