2013-04-18 85 views
9

我想處理服務客戶端拋出的所有WebServiceException。現在有沒有一種好方法可以做到這一點?ServiceClientBase的異常處理程序

例如,我將一個ServiceClientBase傳遞給一個Windows窗體應用程序。我將一個api密鑰傳遞給http頭中的服務器。對於API密鑰無效的任何請求,我想顯示一個消息框,告訴用戶請求未經授權,並且應該設置API密鑰。但我不希望這樣的代碼隨處可見:

try 
{ 
    _client.Get(new ReqDto()); 
} 
catch (WebServiceException ex) 
{ 
    if(ex.StatusCode == 401) 
     Util.ShowUnauthorizedMessageBox(); 
} 

像這樣的事情將是很好:

_client.WebServiceExceptionHandler += TheHandler; 

我知道有本地響應濾波器,我可以掛接到,但我需要物化WebServiceException 。

我在看ServiceClientBase.cs看看我能做什麼,但我會很感激任何幫助。謝謝。

回答

2

如果我可能將此作爲一個設計問題而不是API問題,那麼答案就是包裝您的服務客戶端。就我個人而言,我做了類似的事情,所以我可以在客戶端上記錄服務異常。

這可能是一個起點:

public class MyServiceClient : IDisposable 
{ 
    public ServiceClientBase ServiceClient { get; set; } 

    string _serviceUri; 
    public string ServiceUri 
    { 
     get { return _serviceUri; } 
     set { _serviceUri = value; ServiceUriChanged(); } 
    } 

    public MyServiceClient() 
    { 
     ServiceUri = "http://127.0.0.1:8080"; 
    } 

    public void Dispose() 
    { 
     ServiceClient.Dispose(); 
    } 

    public TResponse Get<TResponse>(IReturn<TResponse> request) 
    { 
     try 
     { 
      return ServiceClient.Get(request); 
     } 
     catch (WebServiceException ex) 
     { 
      if(ex.StatusCode == 401) 
       Util.ShowUnauthorizedMessageBox(); 
     } 
    } 

    void ServiceUriChanged() 
    { 
     if (ServiceClient != null) 
      ServiceClient.Dispose(); 
     ServiceClient = new JsonServiceClient(ServiceUri); 
    } 
} 

隨着時間的推移,你會發現,以間接的這個附加級別其他好處,如增加本地緩存,記錄所有的請求&響應[到調試控制檯。而且,一旦它在您的所有客戶端代碼中使用,維護起來相當便宜。

就API而言,我不認爲它提供了你想要的。就我個人而言,我一直很喜歡它(特別是當你整合像你想要的功能時,IReturn<T>界面有幫助)。但是,如果您對此不滿意,那麼您需要脫離與Demis的對話,以改善它。 ( - =

1

這是比較晚的遊戲,但我遇到了同樣的事情,所以開始挖掘源代碼。實際上有一個簡單的解決方法,覆蓋HandleResponseException方法在任何ServiceClient中使用從評論直銷:

 /// <summary> 
     /// Called by Send method if an exception occurs, for instance a System.Net.WebException because the server 
     /// returned an HTTP error code. Override if you want to handle specific exceptions or always want to parse the 
     /// response to a custom ErrorResponse DTO type instead of ServiceStack's ErrorResponse class. In case ex is a 
     /// <c>System.Net.WebException</c>, do not use 
     /// <c>createWebRequest</c>/<c>getResponse</c>/<c>HandleResponse&lt;TResponse&gt;</c> to parse the response 
     /// because that will result in the same exception again. Use 
     /// <c>ThrowWebServiceException&lt;YourErrorResponseType&gt;</c> to parse the response and to throw a 
     /// <c>WebServiceException</c> containing the parsed DTO. Then override Send to handle that exception. 
     /// </summary> 

我個人做這樣的事情在我的JsonServiceClient

protected override bool HandleResponseException<TResponse>(Exception ex, object request, string requestUri, Func<System.Net.WebRequest> createWebRequest, Func<System.Net.WebRequest, System.Net.WebResponse> getResponse, out TResponse response) 
    { 
     Boolean handled; 
     response = default(TResponse); 
     try 
     { 
      handled = base.HandleResponseException(ex, request, requestUri, createWebRequest, getResponse, out response); 
     } 
     catch (WebServiceException webServiceException) 
     { 
      if(webServiceException.StatusCode > 0) 
       throw new HttpException(webServiceException.StatusCode, webServiceException.ErrorMessage); 
      throw; 
     } 
     return handled; 
    } 
覆蓋以下