ASP.Net Core 2 error handling: How to return forma

2019-03-24 18:15发布

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();
    }
}

2条回答
▲ chillily
2楼-- · 2019-03-24 18:43

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>();
查看更多
做个烂人
3楼-- · 2019-03-24 19:01

Alternatively to middleware, you can create ActionFilterAttribute and change IActionResult

Here is simple example attribuet that for all unhandled exceptions returns 400 Bad request with Exception method.

public class MyUnhandledExceptionFilter : ActionFilterAttribute, IExceptionFilter
{        
    public void OnException(ExceptionContext context)
    {           
        context.Result = new BadRequestObjectResult(context.Exception.Message);
    }
}

You then register it in startup's ConfigureServices method like this

services.AddMvc(options =>
        {
            options.Filters.Add(typeof(MyUnhandledExceptionFilter));
        })

This only catches exceptions that reached MVC, which in most cases is what you need

查看更多
登录 后发表回答