ASP.Net Core 2 error handling: How to return formatted exception details in Http Response?

Anthony Brenelière picture Anthony Brenelière · Feb 5, 2018 · Viewed 15.3k times · Source

I am looking for a way to return the details of any exception that occur when calling a method of my web API.

By default in production environment, error 500 "Internal Server Error" is the only information returned by the API.

It is a private API that is not published over the internet, and the caller application needs to get and store all details in case of exception.

The exception details could be JSON formatted in the HttpResponse content, allowing the caller to read the Message attribute, and the StackTraceString attribute of the exception (No HTTP page like UseDeveloperExceptionPage configuration).

Currently the default Startup Configure method is:

public class Startup
{   
    [...]

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory)
    {
        loggerFactory.AddNLog();
        env.ConfigureNLog(Path.Combine(AppContext.BaseDirectory, "nlog.config"));

        if ( env.IsDevelopment() )
            app.UseDeveloperExceptionPage();
        else
            app.UseStatusCodePages();

        app.UseMvc();
    }
}

Answer

Manuel Allenspach picture Manuel Allenspach · Feb 5, 2018

You could write a custom middleware, which intercepts all exceptions and returns them to the caller:

public class ExceptionHandler
{
    private readonly RequestDelegate _next;

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

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next.Invoke(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        var response = context.Response;
        response.ContentType = "application/json";
        response.StatusCode = (int)HttpStatusCode.InternalServerError;
        await response.WriteAsync(JsonConvert.SerializeObject(new
        {
            // customize as you need
            error = new
            {
                message = exception.Message,
                exception = exception.GetType().Name
            }
        }));
    }
}

and register it in your Startup Configure method:

if (env.IsDevelopment())
    app.UseDeveloperExceptionPage();
else
   app.UseMiddleware<ExceptionHandler>();