前幾天在webapi項目中遇到一個問題:Controller構造函數中拋出異常時全局過濾器捕獲不到,於是網搜一把寫下這篇博客作為總結。
HttpResponseException
通常在WebAPI的Controller中拋出的未處理異常,會以500的形式返回到客戶端。而HttpResponseException
會返回我們指定的狀態碼,如返回501:
public HttpResponseMessage Exception() { //直接在Action中拋出HttpResponseException類型異常 throw new HttpResponseException(HttpStatusCode.NotImplemented); }
在拋出HttpResponseException
時,可將HttpResponseMessage類型的實例作為參數以提供給客戶端更多的信息。
HttpError
public HttpResponseMessage Exception() { //使用Request對象創建返回到客戶端的錯誤信息 Request.CreateErrorResponse() }
CreateErrorResponse
方法是HttpResponseMessage
類型的可擴展方法,該方法最終會調用擴展方法CreateResponse
返回一個HttpResponseMessage
類型的對象(ASP.NET WebAPI中Action的返回值最終都會被轉換為HttpResponseMessage類型的對象),該對象包含一個HttpError
類型實例。
Exception Filters
自定義派生自ExceptionFilterAttribute或IExceptionFilter的異常處理類用於異常的處理。
過濾器可分為三個級別:
- Action
- Controller
- Global
注意:ASP.NET MVC和ASP.NET WebAPI的異常過濾器不可混用
ExceptionHandler
以下情形中的異常,過濾器是無法捕獲到的:
-
Controller構造函數中拋出的異常
-
消息處理器中拋出的異常
-
路由過程中出現的異常
-
其它過濾器中拋出的異常
-
序列化返回內容時拋出的異常
解決方案如下:
自定義異常處理器,兩種方式
public class XfhExceptionHandler : ExceptionHandler { public override void Handle(ExceptionHandlerContext context) { context.Result = new ResponseMessageResult( context.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "發生了不可描述的錯誤!") ); //new InternalServerErrorResult(context.Request); } }
替換ASP.NET WebAPI默認的異常處理器
public static void Register(HttpConfiguration config) { config.Services.Replace(typeof(IExceptionHandler), new XfhExceptionHandler()); }
PS:若要記錄未處理異常日志可實現接口IExceptionLogger或繼承ExceptionLogger
小結
IExceptionFilter只能處理Action中發生的未處理異常,IExceptionHandler可以處理任何地方發生的未處理異常。
相關閱讀
catch all unhandled exceptions in ASP.NET Web Api
Handling Errors in Web API Using Exception Filters and Exception Handlers
Exception Handling in ASP.NET Web API
Global Error Handling in ASP.NET Web API 2
Action Results in Web API 2