问题
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.
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 }
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; } }
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