Web API統一異常處理 【轉載】
前面講了webapi的安全驗證和參數安全,不清楚的朋友,可以看看前面的文章,《Web API系列(二)接口安全和參數校驗》,本文主要介紹Web API異常結果的處理。作為內部或者是對外提供的統一webapi 接口,統一的異常處理,把正確的信息返回給調用者很重要。這樣可以讓接口開發人員,了解具體的原因所在,這樣可以得到有效的錯誤處理。
需要註意的是,webapi異常的狀態碼,盡量不要和業務狀態碼混淆。可以分為兩個不同的字段,或者是狀態碼的規則不同。相關返回數據的格式,可以參考,前面的文章。
1、常規程序異常處理
常規的程序異常,指的是webapi 接口程序在執行的時候出現的各種異常情況,可以使用異常篩選器捕獲所有異常。
1. API自定義錯誤過濾器屬性:ApiExceptionAttribute
/// <summary> /// API自定義錯誤過濾器屬性 /// </summary> public class ApiExceptionHandlingAttribute : ExceptionFilterAttribute { /// <summary> /// 統一對調用異常信息進行處理,返回自定義的異常信息 /// </summary> /// <param name="context">HTTP上下文對象</param> public override void OnException(HttpActionExecutedContext context) { //自定義異常的處理 if (context.Exception is NotImplementedException) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotImplemented) { //封裝處理異常信息,返回指定JSON對象 Content = new StringContent(JsonHelper.ToJson(new ErrorModel((int)HttpStatusCode.NotImplemented, 0, ex.Message)), Encoding.UTF8, "application/json"), ReasonPhrase = "NotImplementedException" }); } else if (context.Exception is TimeoutException) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.RequestTimeout) { //封裝處理異常信息,返回指定JSON對象 Content = new StringContent(JsonHelper.ToJson(new ErrorModel((int)HttpStatusCode.RequestTimeout, 0, ex.Message)), Encoding.UTF8, "application/json"), ReasonPhrase = "TimeoutException" }); } //.....這裏可以根據項目需要返回到客戶端特定的狀態碼。如果找不到相應的異常,統一返回服務端錯誤500 else { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { //封裝處理異常信息,返回指定JSON對象 Content = new StringContent(JsonHelper.ToJson(new ErrorModel((int)HttpStatusCode.InternalServerError, 0, ex.Message)), Encoding.UTF8, "application/json"), ReasonPhrase = "InternalServerErrorException" }); } //base.OnException(context); //記錄關鍵的異常信息 //Debug.WriteLine(context.Exception); } }
2. 定義好了錯誤過濾器,根據實際情況,在不同級別使用統一的異常處理機制。比如,接口action級別,控制器Controller級別或者是全局。
我們目前的使用的是全局進行異常過濾。在ApiBase 增加異常過濾。
[ApiAuth] [ApiExceptionHandling] public class ApiBase : ApiController
2、地址接口異常處理
對於常規的異常,我們通過上面的處理方式,就可以很好進行攔截並處理了,如果接口異常是全局性的,如訪問地不正確,或者調用的接口就不是有效的地址,這樣的話,返回的信息就不會被上面的攔截器進行處理了。
如我們給一個無效的API調用路徑,在瀏覽器中獲得下面錯誤結果。
由於上面結果就無法被我們的常規異常攔截器所捕獲,因此不會輸出經過封裝好的異常信息。
所以如果需要攔截,我們需要增加自己的消息代理處理,用來捕獲這些特殊的異常信息。
/// <summary> /// API自定義錯誤消息處理委托類。 /// 用於處理訪問不到對應API地址的情況,對錯誤進行自定義操作。 /// </summary> public class CustomErrorMessageDelegatingHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) => { HttpResponseMessage response = responseToCompleteTask.Result; HttpError error = null; if (response.TryGetContentValue<HttpError>(out error)) { //添加自定義錯誤處理 //error.Message = "Your Customized Error Message"; } if (error != null) { //獲取拋出自定義異常,有攔截器統一解析 throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound) { //封裝處理異常信息,返回指定JSON對象 Content = new StringContent(JsonHelper.ToJson(new ErrorModel(404, 0, error.Message)), Encoding.UTF8, "application/json"), ReasonPhrase = "Exception" }); } else { return response; } }); } }
同時,在WebApiConfig中,註冊上相關處理
public static class WebApiConfig { public static void Register(HttpConfiguration config) { .............. config.MessageHandlers.Add(new CustomErrorMessageDelegatingHandler());
有了以上這兩種異常處理,我們就可以統一我們的調用規則,並進行異常記錄和顯示了,非常方便。
3、總結
首先,以上這兩種異常處理,我們就可以統一我們的調用規則,但是對於WebApi裏面異常的處理機制,可能還不夠深入,但對於一般項目的異常處理基本夠用。其他朋友,如果還有什麽更好的方案,還望不吝賜教,感謝感謝!
其次,我們目前使用的異常處理,參考於http://www.cnblogs.com/wuhuacong/p/4843422.html。
Web API統一異常處理 【轉載】