Matthew Flynn
Matthew Flynn

Reputation: 3931

Setting Body of caught error in Middleware asp.net core 2

I have followed the following link;

Custom HttpResponseException Middleware Asp.Net Core 2.0

I now want to add a message to the body of the response to give context to the exception.

I modified the middleware Invoke method as follows;

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (HttpStatusCodeException exception)
        {
            context.Response.StatusCode = (int)exception.StatusCode;
            // byte[] data = Encoding.UTF8.GetBytes(exception.Message);
            // await context.Response.Body.WriteAsync(data, 0, data.Length);
            await context.Response.WriteAsync(exception.Message);
            context.Response.Headers.Clear();
        }
    }

However when adding the WriteAsync line to the method I don't get a response from the Api (I am testing through postman).

Can anyone point me in the right direction as to what I am doing wrong here please?

Full code for the class and middleware are below;

namespace Services.WebApi.Middleware
{
    public class HttpErrorHandlerMiddleware
    {

        private readonly RequestDelegate _next;

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

        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (HttpStatusCodeException exception)
            {
                context.Response.StatusCode = (int)exception.StatusCode;
                // byte[] data = Encoding.UTF8.GetBytes(exception.Message);
                // await context.Response.Body.WriteAsync(data, 0, data.Length);
                await context.Response.WriteAsync(exception.Message);
                context.Response.Headers.Clear();
            }
        }
    }

    public static class HttpErrorHandlerMiddlewareExtensions
    {
        public static IApplicationBuilder UseHttpErrorHandlerMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<HttpErrorHandlerMiddleware>();
        }
    }
}

The HttpStatusCodeException class is as follows;

    public class HttpStatusCodeException : Exception
{
    public HttpStatusCode StatusCode { get; set; }

    public HttpStatusCodeException(HttpStatusCode statusCode)
    {
        StatusCode = statusCode;
    }

    public HttpStatusCodeException(HttpStatusCode statusCode, string message) : base(message)
    {
        StatusCode = statusCode;
    }

}

Upvotes: 2

Views: 1517

Answers (1)

Evk
Evk

Reputation: 101443

This

await context.Response.WriteAsync(exception.Message);
context.Response.Headers.Clear();

Is not going to work, because after you sent the respose (via Response.WriteAsync) - headers cannot be changed\cleared, because headers are sent before the response body, and so at this moment are already sent to client. Just change the order like this:

context.Response.Headers.Clear();
await context.Response.WriteAsync(exception.Message);

And it should work as expected. It also worth checking that response has not already started at this point:

if (!context.Response.HasStarted) {
    context.Response.Headers.Clear();
    await context.Response.WriteAsync(exception.Message);
}

Also ensure that you register your middleware before other middleware. Right:

app.UseHttpErrorHandlerMiddleware();
app.UseMvc();

Wrong

app.UseMvc();
app.UseHttpErrorHandlerMiddleware();

Upvotes: 2

Related Questions