[英]How to idiomatically handle HTTP error codes when using RestSharp?
我正在使用RestSharp構建HTTP API客戶端,並且我注意到當服務器返回HTTP錯誤代碼(未授權401,未找到404,內部服務器錯誤500等)時, RestClient.Execute()
不會引發異常-相反,我獲得了具有null .Data
屬性的有效RestResponse
。 我不想在API客戶端中手動檢查每個可能的HTTP錯誤代碼-RestSharp是否提供了一種更好的將這些錯誤傳遞到客戶端應用程序的方法?
進一步的細節。 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屬性仍然為null。 我可以看到 RestResponse.StatusCode
和RestResponse.StatusDescription
屬性中的未授權狀態代碼和錯誤消息-但是對於為何未授權響應不會導致填充ErrorException
字段的原因,我感到困惑。
在嘗試為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時,我的網絡服務返回了HTML格式的404頁面。 這導致response.ErrorException
屬性包含以下字符串:
引用未聲明的實體“ nbsp”。 第n行,位置m。
顯然,RestSharp嘗試將響應解析為XML,即使內容類型為text / html。 也許我會為此向RestSharp提出問題。
當然,在生產環境中,調用自己的服務時永遠都不會收到404,但是我希望此客戶端能夠徹底且可重用。
因此,我可以想到兩種解決方案:
前者很容易做到。 在HandleErrorResponse()
我根據狀態碼的數值構建結果消息(用戶可顯示)和錯誤字符串(可記錄):
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>
,因此我可以設置一個異常過濾器和一個NotFound路由,以返回帶有ResultMessage
屬性中的錯誤或異常消息的可解析響應模型:
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;
}
}
這樣,我的服務響應始終可以由RestSharp解析,並且我可以使用通用的日志記錄方法:
public string HandleErrorResponse<TResponseModel>(IRestRequest request, IRestResponse<<ResponseModel<TResponseModel>> response)
並將實際響應記錄在// (other error handling here)
如果有的話,在// (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);
}
RestSharp添加了布爾屬性IRestResponse.IsSuccessful
,它涵蓋了您的用例。 我找不到任何有關此屬性的文檔,但這是定義該屬性的method的那一行 。
有趣的是,RestSharp認為代碼200-299成功,而CodeCaster認為代碼200-399成功。
檢查成功代碼,並在成功之外獲得其他任何代碼,則拋出或報告錯誤就足夠了。 這通常意味着在每個請求之后檢查HTTP狀態200。 如果創建新資源,則應該獲得狀態201。
對於大多數API /框架,如果沒有其他錯誤,則看到任何其他狀態代碼是非常不尋常的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.