Web API--自定义异常结果的处理
1、常規(guī)的異常處理
統(tǒng)一的異常處理,把正確的信息返回給調(diào)用者很重要,可以讓接口開發(fā)人員或者用戶,了解具體的原因所在,這樣可以得到有效的錯(cuò)誤處理。
參考微信API的處理,微信API,對(duì)于調(diào)用都有一個(gè)錯(cuò)誤信息返回,不會(huì)直接裸露未經(jīng)處理的異常,因此它們都是經(jīng)過了一定的攔截處理,然后把錯(cuò)誤信息包裝提供給接口調(diào)用方的。如下是微信的一些接口處理錯(cuò)誤。
錯(cuò)誤時(shí)微信會(huì)返回錯(cuò)誤碼等信息,JSON數(shù)據(jù)包示例如下(該示例為AppID無效錯(cuò)誤):{"errcode":40013,"errmsg":"invalid appid"}我們根據(jù)自己的需要,定義了一個(gè)統(tǒng)一的錯(cuò)誤信息實(shí)體類,如下所示。
/// <summary>/// 接口返回的錯(cuò)誤信息/// </summary>public class BaseResultJson{/// <summary>/// 錯(cuò)誤代碼/// </summary>public int errcode { get; set; }/// <summary>/// 如果不成功,返回的錯(cuò)誤信息/// </summary>public string errmsg { get; set; }/// <summary>/// 是否成功/// </summary>public bool success { get; set; }}這樣我們就可以把攔截到的錯(cuò)誤信息,轉(zhuǎn)換為這樣一個(gè)方便使用的實(shí)體類信息了。
攔截Web API的調(diào)用異常,一般可以結(jié)合Try Catch的方法,以及異常攔截器進(jìn)行處理,如下是主動(dòng)拋出的一些異常信息處理。
//如果沒有通過,則拋出異常,由異常過濾器統(tǒng)一處理if (!result.success){throw new MyApiException(result.errmsg, result.errcode);}其中MyApiException是自定義的一個(gè)異常信息,用來承載自定義錯(cuò)誤信息的異常類。
異常攔截器,我們?cè)赪eb API里面可以通過Attribute這種標(biāo)簽特性進(jìn)行處理,如下是我在Web API的基類里面定義了一個(gè)異常處理器。
/// <summary>/// 所有接口基類/// </summary>[ExceptionHandling]public class BaseApiController : ApiController這個(gè)特性對(duì)象的定義,它的代碼如下所示。
/// <summary>/// API自定義錯(cuò)誤過濾器屬性/// </summary>public class ExceptionHandlingAttribute : ExceptionFilterAttribute{/// <summary>/// 統(tǒng)一對(duì)調(diào)用異常信息進(jìn)行處理,返回自定義的異常信息/// </summary>/// <param name="context">HTTP上下文對(duì)象</param>public override void OnException(HttpActionExecutedContext context){//自定義異常的處理MyApiException ex = context.Exception as MyApiException;if (ex != null){ throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError){//封裝處理異常信息,返回指定JSON對(duì)象Content = new StringContent(new BaseResultJson(ex.Message, false, ex.errcode).ToJson()),ReasonPhrase = "Exception"});}//記錄關(guān)鍵的異常信息Debug.WriteLine(context.Exception);//常規(guī)異常的處理string msg = string.IsNullOrEmpty(context.Exception.Message) ? "接口出現(xiàn)了錯(cuò)誤,請(qǐng)重試或者聯(lián)系管理員" : context.Exception.Message;throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError){Content = new StringContent(msg),ReasonPhrase = "Critical Exception"});}}根據(jù)這些代碼,我們就可以實(shí)現(xiàn)對(duì)調(diào)用異常的統(tǒng)一封裝處理,讓它給我們返回統(tǒng)一的對(duì)象信息了,如下是其中一個(gè)調(diào)用異常,轉(zhuǎn)換為自定義異常信息后的結(jié)果輸出。
{"errcode":404,"errmsg":"請(qǐng)求的資源不支持 http 方法“POST”。","success":false}這樣我們?cè)谔幚鞼eb API的返回結(jié)果的時(shí)候,可以先處理它的異常信息,具體的處理代碼如下所示。
HttpHelper helper = new HttpHelper();helper.ContentType = "application/json";string content = helper.GetHtml(url, postData, true);VerifyErrorCode(content);T result = JsonConvert.DeserializeObject<T>(content);return result;我們?cè)谏厦婕t色部分的代碼就是先處理異常定義信息,如果有這些異常,我們可以在界面中進(jìn)行異常處理顯示了。
例如,如果自定義異常存在,我們轉(zhuǎn)換后,把對(duì)應(yīng)的信息顯示出來,重新拋出異常即可。
BaseResultJson errorResult = JsonConvert.DeserializeObject<BaseResultJson>(content);//非成功操作才記錄異常,因?yàn)橛行┎僮魇欠祷卣5慕Y(jié)果({"errcode": 0, "errmsg": "ok"})if (errorResult != null && !errorResult.success){string error = string.Format("請(qǐng)求發(fā)生錯(cuò)誤!錯(cuò)誤代碼:{0},說明:{1}", (int)errorResult.errcode, errorResult.errmsg);LogTextHelper.Error(errorResult.ToJson());throw new Exception(error);//拋出錯(cuò)誤}2、地址接口異常處理
對(duì)于常規(guī)的異常,我們通過上面的處理方式,就可以很好進(jìn)行攔截并處理了,如果接口異常是全局性的,如訪問地址簿正確,或者參數(shù)多了幾個(gè)信息,那么調(diào)用的接口就不是有效的地址,這樣的話,返回的信息就不會(huì)被上面的攔截器進(jìn)行處理了。
如我們給一個(gè)無效的API調(diào)用路徑,在瀏覽器中獲得下面錯(cuò)誤結(jié)果。
上面結(jié)果就無法被我們的常規(guī)異常攔截器所捕獲,因此不會(huì)輸出經(jīng)過封裝好的異常信息。
如果需要攔截,我們需要增加自己的消息代理處理,用來捕獲這些特殊的異常信息。
public static class WebApiConfig{public static void Register(HttpConfiguration config){..............config.MessageHandlers.Add(new CustomErrorMessageDelegatingHandler());上面紅色部分就是我們自己添加的消息代理處理類,用來處理一些特殊的異常信息,如下代碼所示。
/// <summary>/// API自定義錯(cuò)誤消息處理委托類。/// 用于處理訪問不到對(duì)應(yīng)API地址的情況,對(duì)錯(cuò)誤進(jìn)行自定義操作。/// </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)){//添加自定義錯(cuò)誤處理//error.Message = "Your Customized Error Message";}if (error != null){//獲取拋出自定義異常,有攔截器統(tǒng)一解析throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound){//封裝處理異常信息,返回指定JSON對(duì)象Content = new StringContent(new BaseResultJson(error.Message, false, 404).ToJson()),ReasonPhrase = "Exception"});}else{return response;}});}}經(jīng)過了上面的處理后,我們進(jìn)一步測(cè)試一下不存在的地址的異常處理結(jié)果,可以看到輸出的內(nèi)容是經(jīng)過了自定義對(duì)象的轉(zhuǎn)換了。
常規(guī)的調(diào)用,如果接口不對(duì)應(yīng),那么錯(cuò)誤也是類似下面的消息
{"errcode":404,"errmsg":"找不到與請(qǐng)求 URI“http://localhost:9001/api/SystemType/Delete?signature=72f8d706c79dc14d70fc3f080d4706748d754021×tamp=1443194061&nonce=0.650359861855563&appid=website_9A39C2A8&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxIiwiaWF0IjoxNDQzMTk0MDM4LCJqdGkiOiI1YmEyYmE5Ni0yZTA4LTQ1ZTgtYTAwNy01MmY3OTkzYTg2NzEiLCJuYW1lIjoiYWRtaW4iLCJjaGFubmVsIjoiMCIsInNoYXJlZGtleSI6IjEyMzRhYmNkIn0.RRXQmmSCJzDK5Or6rmBL5wjd-YIJoEQFc0pOzqhR6IU”匹配的 HTTP 資源。","success":false}有了這些信息,我們就可以統(tǒng)一我們的調(diào)用規(guī)則,并進(jìn)行異常記錄和顯示了,非常方便。
http://www.cnblogs.com/wuhuacong/p/4843422.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Web API--自定义异常结果的处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中间人(说一说中间人的简介)
- 下一篇: SVN Files 的值“