2015-07-20 41 views
13

我建立使用RestSharp的HTTP API客戶端,我注意到,當服務器返回一個HTTP錯誤代碼(401未經授權,404未找到,500內部服務器錯誤等)RestClient.Execute()不拋出異常 - 而我得到一個有效的RestResponse與空.Data財產。我不想在API客戶端中手動檢查每個可能的HTTP錯誤代碼 - RestSharp是否提供了將這些錯誤傳遞給我的客戶端應用程序的更好方法?如何在使用RestSharp時習慣性地處理HTTP錯誤代碼?

一個小的進一步細節。 RestSharp公開Response.ErrorException屬性 - 如果RestClient.Execute<T>()調用導致任何異常,它將通過ErrorException屬性公開,而不是被拋出。他們的文檔包括下面的例子:

// TwilioApi.cs 
public class TwilioApi { 
    const string BaseUrl = "https://api.twilio.com/2008-08-01"; 

    public T Execute<T>(RestRequest request) where T : new() 
    { 
    var client = new RestClient(); 
    client.BaseUrl = BaseUrl; 
    client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey); 
    request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment); // used on every request 
    var response = client.Execute<T>(request); 

    if (response.ErrorException != null) 
    { 
     const string message = "Error retrieving response. Check inner details for more info."; 
     var twilioException = new ApplicationException(message, response.ErrorException); 
     throw twilioException; 
    } 
    return response.Data; 
    } 

} 

我已經通過了我的代碼的模式,但我的API服務器返回一個401 Unauthorized,但該ErrorException屬性仍然爲空。我可以請參閱RestResponse debug watch未授權的狀態碼和RestResponse.StatusCodeRestResponse.StatusDescription屬性中的錯誤消息 - 但我很困惑爲什麼未經授權的響應不會導致ErrorException字段被填充。

回答

0

它應該是足夠的,檢查是否有成功的代碼,並拋出或者如果你從成功中得到任何其他代碼分開報告錯誤。這通常意味着在每次請求後檢查HTTP狀態200。如果您創建一個新的資源,你應該期望狀態201

對於大多數的API /框架,這是非常非常不尋常看到任何其他狀態代碼,除了這些,如果沒有出現了偏差。

17

我試圖創建一個RestSharp的WebAPI客戶一般錯誤處理程序遇到同樣的問題。鑑於這些擴展方法:

public static class RestSharpExtensionMethods 
{ 
    public static bool IsSuccessful(this IRestResponse response) 
    { 
     return response.StatusCode.IsSuccessStatusCode() 
      && response.ResponseStatus == ResponseStatus.Completed; 
    } 

    public static bool IsSuccessStatusCode(this HttpStatusCode responseCode) 
    { 
     int numericResponse = (int)responseCode; 
     return numericResponse >= 200 
      && numericResponse <= 399; 
    } 
} 

我提出,所需的響應要被反序列化請求:

public async Task<ResponseModel<TResponse>> PerformRequestAsync<TResponse>(IRestRequest request) 
{ 
    var response = await _client.ExecuteTaskAsync<ResponseModel<TResponse>>(request); 
    ResponseModel<TResponse> responseData; 

    if (response.IsSuccessful()) 
    { 
     responseData = response.Data; 
    } 
    else 
    { 
     string resultMessage = HandleErrorResponse<TResponse>(request, response); 

     responseData = new ResponseModel<TResponse>   
     { 
      Success = false, 
      ResultMessage = resultMessage 
     }; 
    } 

    return responseData; 
} 

然而,在測試過程中,我發現,當我沒有錯誤處理被配置用於這種情況下,當請求未映射的URL時,我的web服務返回了一個HTML格式的404頁面。這導致response.ErrorException屬性包含以下字符串:

引用未聲明的實體'nbsp'。第n行,位置m。

顯然,RestSharp嘗試將響應解析爲XML,即使內容類型爲text/html。也許我會爲此爲RestSharp提出問題。

當然,在生產,呼籲自己的服務時,你不應該得到一個404,但我想這個客戶是徹底的和可重複使用的。

因此,有兩種解決方案,我能想到的:

  • 檢查狀態代碼並顯示描述
  • 確保服務返回一個錯誤的對象,你可以分析

前很容易完成。在HandleErrorResponse()我建立結果信息(用戶呈現的)和基於狀態碼的數值錯誤字符串(爲loggable):

public string HandleErrorResponse(IRestRequest request, IRestResponse response) 
{ 
    string statusString = string.Format("{0} {1} - {2}", (int)response.StatusCode, response.StatusCode, response.StatusDescription); 
    string errorString = "Response status: " + statusString; 

    string resultMessage = ""; 
    if (!response.StatusCode.IsScuccessStatusCode()) 
    { 
     if (string.IsNullOrWhiteSpace(resultMessage)) 
     { 
      resultMessage = "An error occurred while processing the request: " 
          + response.StatusDescription; 
     } 
    } 
    if (response.ErrorException != null) 
    { 
     if (string.IsNullOrWhiteSpace(resultMessage)) 
     { 
      resultMessage = "An exception occurred while processing the request: " 
          + response.ErrorException.Message; 
     } 
     errorString += ", Exception: " + response.ErrorException; 
    } 

    // (other error handling here) 

    _logger.ErrorFormat("Error response: {0}", errorString); 

    return resultMessage; 
} 

現在我的API響應始終被包裹在我製作的ResponseModel<T>,我

public class HandleErrorAttribute : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     // (log context.Exception here) 

     context.Response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, new ResponseModel<object> 
     { 
      Success = false, 
      ResultMessage = "An exception occurred while processing the request: " + context.Exception.Message 
     }); 
    } 
} 

而且:

public class ErrorController : ApiController 
{ 
    public HttpResponseMessage Handle404() 
    { 
     const string notFoundString = "The requested resource could not be found"; 

     var responseMessage = Request.CreateResponse(HttpStatusCode.NotFound, new ResponseModel<object> 
     { 
      Success = false, 
      ResultMessage = notFoundString 
     }); 

     responseMessage.ReasonPhrase = notFoundString; 

     return responseMessage; 
    } 
} 
set up an exception filter and a NotFound routeResultMessage屬性與錯誤或異常信息返回一個可分析的響應模型

這樣從我服務的響應總是可以通過RestSharp解析,我可以使用通用的測井方法:

public string HandleErrorResponse<TResponseModel>(IRestRequest request, IRestResponse<<ResponseModel<TResponseModel>> response) 

,並記錄實際響應在// (other error handling here),如果有的話:

if (response.Data != null && !string.IsNullOrWhiteSpace(response.Data.ResultMessage)) 
{ 
    resultMessage = response.Data.ResultMessage; 
    errorString += string.Format(", Service response: \"{0}\"", response.Data.ResultMessage); 
} 
0

RestSharp已經添加了布爾屬性IRestResponse.IsSuccessful,它涵蓋了您的用例。我找不到任何涉及此屬性的文檔,但是here's the line that defines the property's method

有趣的是,RestSharp認爲代碼200-299成功,而CodeCaster認爲代碼200-399成功。

相關問題