其實對於C#異常處理你們都不陌生,可是對於在WeiApi上的異常處理實際上也和傳統異常處理區別不大,可是卻通過封裝可讓異常更加友好,https://docs.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling,經過微軟的官方介紹,咱們能夠知道WeiApi能夠簡單概述爲三種異常,接下來咱們圍繞這三種異常給出例子,如何封裝和處理以上三種異常html
異常過濾器實現了System.Web.Http.Filters.IExceptionFilter接口。編寫異常過濾器最簡單的方法是從System.Web.Http.Filters.ExceptionFilterAttribute類派生並重寫OnException方法。Microsoft給出的關於異常過濾器解釋,那麼如何實現呢?經過閱讀《Asp.NET WEB API2 框架揭祕》,咱們知道每一次客戶端請求API都會經過HTTP請求,服務端獲得結果輸出response到客戶端。這個過程當中,一旦服務端發生異常,會統一貫客戶端返回500的錯誤。web
那麼在Web API中如何定義NotImplementedException類?首先在App_Start裏面新建一個類WebApiExceptionFilterAttribute.cs,繼承ExceptionFilterAttribute,重寫OnException方法,代碼以下api
1 public class WebApiExceptionFilterAttribute : ExceptionFilterAttribute 2 { 3 //重寫基類的異常處理方法 4 public override void OnException(HttpActionExecutedContext actionExecutedContext) 5 { 6 //1.異常日誌記錄(正式項目裏面通常是用log4net記錄異常日誌) 7 Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "——" + 8 actionExecutedContext.Exception.GetType().ToString() + ":" + actionExecutedContext.Exception.Message + "——堆棧信息:" + 9 actionExecutedContext.Exception.StackTrace); 10 11 //2.返回調用方具體的異常信息 12 if (actionExecutedContext.Exception is NotImplementedException) 13 { 14 actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented); 15 } 16 else if (actionExecutedContext.Exception is TimeoutException) 17 { 18 actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.RequestTimeout); 19 } 20 //.....這裏能夠根據項目須要返回到客戶端特定的狀態碼。若是找不到相應的異常,統一返回服務端錯誤500 21 else 22 { 23 actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError); 24 } 25 26 base.OnException(actionExecutedContext); 27 } 28 }
代碼解析:經過判斷異常的具體類型,向客戶端返回不一樣的http狀態碼,示例裏面寫了兩個,能夠根據項目的實際狀況加一些特定的咱們想要捕獲的異常,而後將對應的狀態碼寫入http請求的response裏面,對於一些咱們沒法判斷類型的異常,統一返回服務端錯誤500。Microsoft也有一個代碼實現,可是沒有封裝服務器
要將過濾器應用於特定操做,請將過濾器做爲屬性添加到操做中:ide
public class ProductsController : ApiController { [NotImplExceptionFilter] public Contact GetContact(int id) { throw new NotImplementedException("This method is not implemented"); } }
要將過濾器應用於控制器上的全部操做,請將過濾器做爲屬性添加到控制器類中:post
[NotImplExceptionFilter] public class ProductsController : ApiController { // ... }
要將過濾器全局應用於全部Web API控制器,請將過濾器實例添加到GlobalConfiguration.Configuration.Filters集合中。此集合中的執行篩選器適用於任何Web API控制器操做。ui
GlobalConfiguration.Configuration.Filters.Add( new ProductStore.NotImplExceptionFilterAttribute());
若是須要,甚至能夠向Status Code裏面寫入自定義的描述信息,而且還能夠向咱們的Response的Content裏面寫入咱們想要的信息。咱們稍微改下OnException方法:this
if (actionExecutedContext.Exception is NotImplementedException) { var oResponse = new HttpResponseMessage(HttpStatusCode.NotImplemented); oResponse.Content = new StringContent("方法不被支持"); oResponse.ReasonPhrase = "This Func is Not Supported"; actionExecutedContext.Response = oResponse; }
異常過濾器是針對接口控制器以及全局定義,通常返回的都是服務器級別的錯誤,可是有的時候咱們須要定義業務異常的代碼,那麼若是是業務異常的狀況下咱們就可使用HttpResponseException自定義異常,以下述代碼:url
public Product GetProduct(int id) { Product item = repository.Get(id); if (item == null) { var resp = new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent(string.Format("沒有找到產品ID = {0}的產品", id)), ReasonPhrase = "Product ID Not Found" } throw new HttpResponseException(resp); } return item; }
能夠看到具體的業務異常信息是經過HttpResponseMessage封裝,最後由HttpResponseException拋出,Microsoft沒有解釋HttpResponseMessage是什麼,起初筆者覺得這是一個HttpResponseException的子類,可是跟蹤了後發現HttpResponseMessage 繼承了IDisposable接口,而IDisposable接口的主要用途是釋放非託管的資源。 垃圾回收器自動釋放再也不使用該對象時分配給託管對象的內存。 可是,不可能預測將發生垃圾回收。 此外,垃圾回收器具備不知道如窗口句柄的非託管資源,或打開文件和流。從描述上來看使用HttpResponseMessage時就表明發生了異常而且進行一次資源管理的回收,因此筆者認爲,使用HttpResponseMessage能夠更清晰的描述業務中所發生的 異常,而且在返回異常的時候進行一次垃圾回收,減小程序資源浪費
HttpError對象提供了一個一致的方式在迴應主體中返回的錯誤信息。如下示例顯示如何在響應正文中使用HttpError返回HTTP狀態碼404(Not Found)。經過Microsoft的解釋就能夠知道HttpError提供的是狀態碼返回,那麼實際應用上更多的是將其和HttpResponseException一塊兒使用。
public Product GetProduct(int id) { Product item = repository.Get(id); if (item == null) { var message = string.Format("Product with id = {0} not found", id); throw new HttpResponseException( Request.CreateErrorResponse(HttpStatusCode.NotFound, message)); } else { return item; } }
借鑑(Microsoft官網)ASP.NET Web API中的異常處理
在通常的項目中,能夠定義好一些全體的關於服務器端的異常處理,而且封裝好一個HttpResponseException自定義異常的處理,無需捕獲HttpResponseException異常,Api會本身處理這個異常的,而且最好爲每一個異常給出更加詳細的HTTP狀態碼,可讓異常更加精細友好