C#進階--WebApi異常處理機制

                 其實對於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     }
View Code

             代碼解析:經過判斷異常的具體類型,向客戶端返回不一樣的http狀態碼,示例裏面寫了兩個,能夠根據項目的實際狀況加一些特定的咱們想要捕獲的異常,而後將對應的狀態碼寫入http請求的response裏面,對於一些咱們沒法判斷類型的異常,統一返回服務端錯誤500。Microsoft也有一個代碼實現,可是沒有封裝服務器

 註冊異常過濾

         有幾種方法能夠註冊Web API異常過濾器: 
框架

  • 接口級別
  • 控制器級別
  • 全局配置

       要將過濾器應用於特定操做,請將過濾器做爲屬性添加到操做中: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自定義異常信息

                異常過濾器是針對接口控制器以及全局定義,通常返回的都是服務器級別的錯誤,可是有的時候咱們須要定義業務異常的代碼,那麼若是是業務異常的狀況下咱們就可使用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對象提供了一個一致的方式在迴應主體中返回的錯誤信息。如下示例顯示如何在響應正文中使用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;
    }
}

總結

             借鑑C#進階系列——WebApi 異常處理解決方案

             借鑑(Microsoft官網)ASP.NET Web API中的異常處理

             在通常的項目中,能夠定義好一些全體的關於服務器端的異常處理,而且封裝好一個HttpResponseException自定義異常的處理,無需捕獲HttpResponseException異常,Api會本身處理這個異常的,而且最好爲每一個異常給出更加詳細的HTTP狀態碼,可讓異常更加精細友好

相關文章
相關標籤/搜索