Returning exceptions as JSON messages

眉间皱痕 提交于 2019-12-06 00:09:33

问题


I am developing an API with ASP.NET Core and I am struggling with the exception handling.

When any exception occurs, or in any controller where I want to return custom errors with different status codes, I want to return JSON-formatted exception reports. I do not need an HTML in the error responses.

I'm not sure if I should use middleware for this, or something else. How should I return JSON exceptions in an ASP.NET Core API?


回答1:


An exception filter (either as an attribute, or a global filter) is what you are looking for. From the docs:

Exception filters handle unhandled exceptions, including those that occur during controller creation and model binding. They are only called when an exception occurs in the pipeline. They can provide a single location to implement common error handling policies within an app.

If you want any unhandled exception to be returned as JSON, this is the simplest method:

public class JsonExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        var result = new ObjectResult(new
        {
            code = 500,
            message = "A server error occurred.",
            detailedMessage = context.Exception.Message
        });

        result.StatusCode = 500;
        context.Result = result;
    }
}

You can customize the response to add as much detail as you want. The ObjectResult will be serialized to JSON.

Add the filter as a global filter for MVC in Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(JsonExceptionFilter));
    });
}



回答2:


Ok, I got a working solution, that I am pretty happy with.

  1. Add middleware: In the Configure Method, register the middleware (comes with ASP.NET Core).

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        // logging stuff, etc.
    
        app.UseStatusCodePagesWithReExecute("/error/{0}");
        app.UseExceptionHandler("/error");
    
        app.UseMvc(); // if you are using Mvc
    
        // probably other middleware stuff 
    }
    
  2. Create a Class for Messages Write a simple class that represents instances of JSON Error Messages you want to send as a request in any error case:

    public class ExceptionMessageContent
    {
    
        public string Error { get; set; }
        public string Message { get; set; }
    
    }
    
  3. Create Error Controller add the Error Controller that handles all expected and unexpected errors. Note, that these routes correspond to the middleware configuration.

    [Route("[controller]")]
    public class ErrorController : Controller
    {
    
        [HttpGet]
        [Route("")]
        public IActionResult ServerError()
        {
    
            var feature = this.HttpContext.Features.Get<IExceptionHandlerFeature>();
            var content = new ExceptionMessageContent()
            {
                Error = "Unexpected Server Error",
                Message = feature?.Error.Message
            };
            return Content( JsonConvert.SerializeObject( content ), "application/json" );
    
        }
    
    
        [HttpGet]
        [Route("{statusCode}")]
        public IActionResult StatusCodeError(int statusCode)
        {
    
            var feature = this.HttpContext.Features.Get<IExceptionHandlerFeature>();
            var content = new ExceptionMessageContent() { Error = "Server Error", Message = $"The Server responded with status code {statusCode}" };
            return Content( JsonConvert.SerializeObject( content ), "application/json" );
    
        }
    }
    

Now, when I want to throw an error anywhere, I can just do that. The request gets redirected to the error handler and sends a 500 with a nice formatted error message. Also, 404 and other codes are handled gracefully. Any custom status codes I want to send, I can also return them with an instance of my ExceptionMessageContent, for example:

// inside controller, returning IActionResult

var content = new ExceptionMessageContent() { 
    Error = "Bad Request", 
    Message = "Details of why this request is bad." 
};

return BadRequest( content );


来源:https://stackoverflow.com/questions/38664207/returning-exceptions-as-json-messages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!