1. 程式人生 > >Web API統一異常處理 【轉載】

Web API統一異常處理 【轉載】

perror 錯誤 gif mode handlers ttr 服務 class 篩選

 前面講了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統一異常處理 【轉載】