2016-07-29 116 views
4

我正在开发一个带有ASP.NET Core的API,我正在努力处理异常。将异常作为JSON消息返回

当发生任何异常时,或者在任何想要使用不同状态代码返回自定义错误的控制器中,我想返回JSON格式的异常报告。在错误响应中我不需要HTML。

我不确定我是否应该使用中间件来做这个或其他的事情。我应该如何在ASP.NET Core API中返回JSON异常?

+1

很抱歉,但“不工作”是一句废话。请检查[如何创建最小,完整和可验证示例](http://stackoverflow.com/help/mcve)。 –

+0

对不起,在训练时写下了这个问题。当我回到办公室时,会详细阐述它。 – Hinrich

+1

@Hinrich我认为这个问题有一个很好的经典答案的潜力,所以我冒昧地编辑了一些并提出了一个解决方案。如果您觉得我的问题含义太多,请随时回滚或进一步编辑。 –

回答

4

好吧,我得到了一个工作方案,我是用很开心。

  1. 添加中间件: 在Configure方法,注册中间件(自带ASP.NET核心)。

    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. 创建消息类 编写一个简单的类,它表示的JSON错误消息情况下你想发送的任何错误的情况下一个请求:

    public class ExceptionMessageContent 
    { 
    
        public string Error { get; set; } 
        public string Message { get; set; } 
    
    } 
    
  3. 创建错误控制器 添加错误控制器可处理所有预期和意外的错误。请注意,这些路由与中间件配置相对应。

    [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"); 
    
        } 
    } 
    

现在,当我想在任何地方抛出一个错误,我可以做到这一点。该请求被重定向到错误处理程序并发送一个带有很好格式化错误消息的500。此外,404和其他代码处理正常。我想送任何自定义状态代码,我也可以用我的ExceptionMessageContent的实例回报他们,例如:

// inside controller, returning IActionResult 

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

return BadRequest(content); 
+2

@ downvoter:请留下你为什么downvoted的评论。 – Hinrich

+0

不错,完美的作品。 – saZmer

3

异常过滤器(作为属性或全局过滤器)是您正在查找的内容。来自docs

异常过滤器处理未处理的异常,包括在控制器创建和模型绑定期间发生的异常。只有在管道中发生异常时才会调用它们。他们可以提供一个位置来实现应用程序中的常见错误处理策略。

如果你想任何未处理的异常将返回JSON,这是最简单的方法:

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

您可以自定义响应,只要你想添加尽可能多的细节。 ObjectResult将被序列化为JSON。

添加过滤器在启动时的MVC全局过滤器:

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

这处理我所有未捕获的故障,这是一个好的开始。谢谢。但是,如果我想以编程方式从控制器返回“BadRequest”或任何其他状态代码,该怎么办? – Hinrich

+3

请注意,Exception过滤器仅处理MVC异常,ASP.NET Core中更通用的方法是使用ExceptionHandler中间件:http://stackoverflow.com/documentation/asp.net-core/1479/middleware/4815/using-the -exceptionhandler-middleware-to-send-custom-json-error-to-client#t = 201608011043382097082 – Set