2016-07-29 83 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