1. 程式人生 > >WebApi 異常處理解決方案

WebApi 異常處理解決方案

閱讀目錄
一、使用異常篩選器捕獲所有異常
二、HttpResponseException自定義異常資訊
三、返回HttpError
四、總結
一、使用異常篩選器捕獲所有異常
一般情況下,WebApi作為服務使用,每次客戶端傳送http請求到我們的WebApi服務裡面,服務端得到結果輸出response到客戶端。這個過程中,一旦服務端發生異常,會統一向客戶端返回500的錯誤

[HttpGet]publicstringGetAllChargingData([FromUri]TB_CHARGING obj){thrownewNotImplementedException("方法不被支援");}

我們來看看http請求
這裡寫圖片描述
而有些時候,我們客戶端需要得到更加精確的錯誤碼來判斷異常型別,怎麼辦呢?

記得在介紹AOP的時候,我們介紹過MVC裡面的IExceptionFilter介面,這個介面用於定義異常篩選器所需的方法,在WebApi裡面,也有這麼一個異常篩選器,下面我們通過一個例項來看看具體如何實現。

首先在App_Start裡面新建一個類WebApiExceptionFilterAttribute.cs,繼承ExceptionFilterAttribute,重寫OnException方法

publicclassWebApiExceptionFilterAttribute:ExceptionFilterAttribute
{//重寫基類的異常處理方法publicoverridevoidOnException(HttpActionExecutedContext actionExecutedContext){//1.異常日誌記錄(正式專案裡面一般是用log4net記錄異常日誌)Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")+"——"+ actionExecutedContext.Exception.GetType().ToString()+":"+ actionExecutedContext.Exception.Message
+"——堆疊資訊:"+ actionExecutedContext.Exception.StackTrace);//2.返回呼叫方具體的異常資訊if(actionExecutedContext.ExceptionisNotImplementedException){ actionExecutedContext.Response=newHttpResponseMessage(HttpStatusCode.NotImplemented);}elseif(actionExecutedContext.ExceptionisTimeoutException){ actionExecutedContext.Response=newHttpResponseMessage(HttpStatusCode.RequestTimeout);}//.....這裡可以根據專案需要返回到客戶端特定的狀態碼。如果找不到相應的異常,統一返回服務端錯誤500else{ actionExecutedContext.Response=newHttpResponseMessage(HttpStatusCode.InternalServerError);}base.OnException(actionExecutedContext);}}

程式碼解析:通過判斷異常的具體型別,向客戶端返回不同的http狀態碼,示例裡面寫了兩個,可以根據專案的實際情況加一些特定的我們想要捕獲的異常,然後將對應的狀態碼寫入http請求的response裡面,對於一些我們無法判斷型別的異常,統一返回服務端錯誤500。關於http的狀態碼,framework裡面定義了一些常見的型別,我們大概看看:

#region 程式集 System.dll, v4.0.0.0// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.dll#endregionusingSystem;namespaceSystem.Net{// 摘要: //     包含為 HTTP 定義的狀態程式碼的值。publicenumHttpStatusCode{// 摘要: //     等效於 HTTP 狀態 100。 System.Net.HttpStatusCode.Continue 指示客戶端可能繼續其請求。Continue=100,//// 摘要: //     等效於 HTTP 狀態 101。 System.Net.HttpStatusCode.SwitchingProtocols 指示正在更改協議版本或協議。SwitchingProtocols=101,//// 摘要: //     等效於 HTTP 狀態 200。 System.Net.HttpStatusCode.OK 指示請求成功,且請求的資訊包含在響應中。 這是最常接收的狀態程式碼。 OK =200,//// 摘要: //     等效於 HTTP 狀態 201。 System.Net.HttpStatusCode.Created 指示請求導致在響應被髮送前建立新資源。Created=201,//// 摘要: //     等效於 HTTP 狀態 202。 System.Net.HttpStatusCode.Accepted 指示請求已被接受做進一步處理。Accepted=202,//// 摘要: //     等效於 HTTP 狀態 203。 System.Net.HttpStatusCode.NonAuthoritativeInformation 指示返回的元資訊來自快取副本而不是原始伺服器,因此可能不正確。NonAuthoritativeInformation=203,//// 摘要: //     等效於 HTTP 狀態 204。 System.Net.HttpStatusCode.NoContent 指示已成功處理請求並且響應已被設定為無內容。NoContent=204,//// 摘要: //     等效於 HTTP 狀態 205。 System.Net.HttpStatusCode.ResetContent 指示客戶端應重置(或重新載入)當前資源。ResetContent=205,//// 摘要: //     等效於 HTTP 狀態 206。 System.Net.HttpStatusCode.PartialContent 指示響應是包括位元組範圍的 GET//     請求所請求的部分響應。PartialContent=206,//// 摘要: //     等效於 HTTP 狀態 300。 System.Net.HttpStatusCode.MultipleChoices 指示請求的資訊有多種表示形式。//     預設操作是將此狀態視為重定向,並遵循與此響應關聯的 Location 標頭的內容。MultipleChoices=300,//// 摘要: //     等效於 HTTP 狀態 300。 System.Net.HttpStatusCode.Ambiguous 指示請求的資訊有多種表示形式。 預設操作是將此狀態視為重定向,並遵循與此響應關聯的//     Location 標頭的內容。Ambiguous=300,//// 摘要: //     等效於 HTTP 狀態 301。 System.Net.HttpStatusCode.MovedPermanently 指示請求的資訊已移到 Location//     頭中指定的 URI 處。 接收到此狀態時的預設操作為遵循與響應關聯的 Location 頭。MovedPermanently=301,//// 摘要: //     等效於 HTTP 狀態 301。 System.Net.HttpStatusCode.Moved 指示請求的資訊已移到 Location 頭中指定的//     URI 處。 接收到此狀態時的預設操作為遵循與響應關聯的 Location 頭。 原始請求方法為 POST 時,重定向的請求將使用 GET 方法。Moved=301,//// 摘要: //     等效於 HTTP 狀態 302。 System.Net.HttpStatusCode.Found 指示請求的資訊位於 Location 頭中指定的//     URI 處。 接收到此狀態時的預設操作為遵循與響應關聯的 Location 頭。 原始請求方法為 POST 時,重定向的請求將使用 GET 方法。Found=302,//// 摘要: //     等效於 HTTP 狀態 302。 System.Net.HttpStatusCode.Redirect 指示請求的資訊位於 Location 頭中指定的//     URI 處。 接收到此狀態時的預設操作為遵循與響應關聯的 Location 頭。 原始請求方法為 POST 時,重定向的請求將使用 GET 方法。Redirect=302,//// 摘要: //     等效於 HTTP 狀態 303。 作為 POST 的結果,System.Net.HttpStatusCode.SeeOther 將客戶端自動重定向到//     Location 頭中指定的 URI。 用 GET 生成對 Location 標頭所指定的資源的請求。SeeOther=303,//// 摘要: //     等效於 HTTP 狀態 303。 作為 POST 的結果,System.Net.HttpStatusCode.RedirectMethod 將客戶端自動重定向到//     Location 頭中指定的 URI。 用 GET 生成對 Location 標頭所指定的資源的請求。RedirectMethod=303,//// 摘要: //     等效於 HTTP 狀態 304。 System.Net.HttpStatusCode.NotModified 指示客戶端的快取副本是最新的。 未傳輸此資源的內容。NotModified=304,//// 摘要: //     等效於 HTTP 狀態 305。 System.Net.HttpStatusCode.UseProxy 指示請求應使用位於 Location 頭中指定的//     URI 的代理伺服器。UseProxy=305,//// 摘要: //     等效於 HTTP 狀態 306。 System.Net.HttpStatusCode.Unused 是未完全指定的 HTTP/1.1 規範的建議擴充套件。Unused=306,//// 摘要: //     等效於 HTTP 狀態 307。 System.Net.HttpStatusCode.RedirectKeepVerb 指示請求資訊位於 Location//     頭中指定的 URI 處。 接收到此狀態時的預設操作為遵循與響應關聯的 Location 頭。 原始請求方法為 POST 時,重定向的請求還將使用//     POST 方法。RedirectKeepVerb=307,//// 摘要: //     等效於 HTTP 狀態 307。 System.Net.HttpStatusCode.TemporaryRedirect 指示請求資訊位於 Location//     頭中指定的 URI 處。 接收到此狀態時的預設操作為遵循與響應關聯的 Location 頭。 原始請求方法為 POST 時,重定向的請求還將使用//     POST 方法。TemporaryRedirect=307,//// 摘要: //     等效於 HTTP 狀態 400。 System.Net.HttpStatusCode.BadRequest 指示伺服器未能識別請求。 如果沒有其他適用的錯誤,或者不知道準確的錯誤或錯誤沒有自己的錯誤程式碼,則傳送//     System.Net.HttpStatusCode.BadRequest。BadRequest=400,//// 摘要: //     等效於 HTTP 狀態 401。 System.Net.HttpStatusCode.Unauthorized 指示請求的資源要求身份驗證。 WWW-Authenticate//     頭包含如何執行身份驗證的詳細資訊。Unauthorized=401,//// 摘要: //     等效於 HTTP 狀態 402。 保留 System.Net.HttpStatusCode.PaymentRequired 以供將來使用。PaymentRequired=402,//// 摘要: //     等效於 HTTP 狀態 403。 System.Net.HttpStatusCode.Forbidden 指示伺服器拒絕滿足請求。Forbidden=403,//// 摘要: //     等效於 HTTP 狀態 404。 System.Net.HttpStatusCode.NotFound 指示請求的資源不在伺服器上。NotFound=404,//// 摘要: //     等效於 HTTP 狀態 405。 System.Net.HttpStatusCode.MethodNotAllowed 指示請求的資源上不允許請求方法(POST//     或 GET)。MethodNotAllowed=405,//// 摘要: //     等效於 HTTP 狀態 406。 System.Net.HttpStatusCode.NotAcceptable 指示客戶端已用 Accept 頭指示將不接受資源的任何可用表示形式。NotAcceptable=406,//// 摘要: //     等效於 HTTP 狀態 407。 System.Net.HttpStatusCode.ProxyAuthenticationRequired 指示請求的代理要求身份驗證。//     Proxy-authenticate 頭包含如何執行身份驗證的詳細資訊。ProxyAuthenticationRequired=407,//// 摘要: //     等效於 HTTP 狀態 408。 System.Net.HttpStatusCode.RequestTimeout 指示客戶端沒有在伺服器期望請求的時間內傳送請求。RequestTimeout=408,//// 摘要: //     等效於 HTTP 狀態 409。 System.Net.HttpStatusCode.Conflict 指示由於伺服器上的衝突而未能執行請求。Conflict=409,//// 摘要: //     等效於 HTTP 狀態 410。 System.Net.HttpStatusCode.Gone 指示請求的資源不再可用。Gone=410,//// 摘要: //     等效於 HTTP 狀態 411。 System.Net.HttpStatusCode.LengthRequired 指示缺少必需的 Content-length//     頭。LengthRequired=411,//// 摘要: //     等效於 HTTP 狀態 412。 System.Net.HttpStatusCode.PreconditionFailed 指示為此請求設定的條件失敗,且無法執行此請求。//     條件是用條件請求標頭(如 If-Match、If-None-Match 或 If-Unmodified-Since)設定的。PreconditionFailed=412,//// 摘要: //     等效於 HTTP 狀態 413。 System.Net.HttpStatusCode.RequestEntityTooLarge 指示請求太大,伺服器無法處理。RequestEntityTooLarge=413,//// 摘要: //     等效於 HTTP 狀態 414。 System.Net.HttpStatusCode.RequestUriTooLong 指示 URI 太長。RequestUriTooLong=414,//// 摘要: //     等效於 HTTP 狀態 415。 System.Net.HttpStatusCode.UnsupportedMediaType 指示請求是不支援的型別。UnsupportedMediaType=415,//// 摘要: //     等效於 HTTP 狀態 416。 System.Net.HttpStatusCode.RequestedRangeNotSatisfiable 指示無法返回從資源請求的資料範圍,因為範圍的開頭在資源的開頭之前,或因為範圍的結尾在資源的結尾之後。RequestedRangeNotSatisfiable=416,//// 摘要: //     等效於 HTTP 狀態 417。 System.Net.HttpStatusCode.ExpectationFailed 指示伺服器未能符合 Expect//     頭中給定的預期值。ExpectationFailed=417,//UpgradeRequired=426,//// 摘要: //     等效於 HTTP 狀態 500。 System.Net.HttpStatusCode.InternalServerError 指示伺服器上發生了一般錯誤。InternalServerError=500,//// 摘要: //     等效於 HTTP 狀態 501。 System.Net.HttpStatusCode.NotImplemented 指示伺服器不支援請求的函式。NotImplemented=501,//// 摘要: //     等效於 HTTP 狀態 502。 System.Net.HttpStatusCode.BadGateway 指示中間代理伺服器從另一代理或原始伺服器接收到錯誤響應。BadGateway=502,//// 摘要: //     等效於 HTTP 狀態 503。 System.Net.HttpStatusCode.ServiceUnavailable 指示伺服器暫時不可用,通常是由於過多載入或維護。ServiceUnavailable=503,//// 摘要: //     等效於 HTTP 狀態 504。 System.Net.HttpStatusCode.GatewayTimeout 指示中間代理伺服器在等待來自另一個代理或原始伺服器的響應時已超時。GatewayTimeout=504,//// 摘要: //     等效於 HTTP 狀態 505。 System.Net.HttpStatusCode.HttpVersionNotSupported 指示伺服器不支援請求的//     HTTP 版本。HttpVersionNotSupported=505,}}