使用RestSharp时如何以惯用方式处理HTTP错误代码? [英] How to idiomatically handle HTTP error codes when using RestSharp?

查看:1711
本文介绍了使用RestSharp时如何以惯用方式处理HTTP错误代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用RestSharp构建HTTP API客户端,我注意到当服务器返回HTTP错误代码(401 Unauthorized,404 Not Found,500 Internal Server Error等) RestClient.Execute()不会抛出异常 - 而是使用null .Data获得有效的 RestResponse 属性。我不想在我的API客户端中手动检查每个可能的HTTP错误代码 - RestSharp是否提供了将这些错误传递给我的客户端应用程序的更好方法?

I'm building an HTTP API client using RestSharp, and I've noticed that when the server returns an HTTP error code (401 Unauthorized, 404 Not Found, 500 Internal Server Error, etc.) the RestClient.Execute() doesn't throw an exception - instead I get a valid RestResponse with a null .Data property. I don't want to manually check for every possible HTTP error code within my API client - does RestSharp provide a better way of passing these errors to my client application?

A更进一步的细节。 RestSharp公开一个 Response.ErrorException 属性 - 如果 RestClient.Execute< T>()调用导致任何异常,它将通过 ErrorException 属性公开,而不是被抛出。他们的文档包括以下示例:

A little further detail. RestSharp exposes a Response.ErrorException property - if the RestClient.Execute<T>() call causes any exception, it'll be exposed via the ErrorException property instead of being thrown. Their documentation includes the following example:

// 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。我可以在<$中查看未经授权的状态代码和错误消息c $ c> RestResponse.StatusCode 和 RestResponse.StatusDescription 属性 - 但我很困惑为什么未经授权的响应不会导致 ErrorException 正在填充的字段。

I've adopted that pattern in my code, but my API server is returning a 401 Unauthorized and yet the ErrorException property is still null. I can see the Unauthorized status code and error message in the RestResponse.StatusCode and RestResponse.StatusDescription properties - but I'm confused as to why an unauthorized response wouldn't result in the ErrorException field being populated.

推荐答案

我在尝试时遇到了同样的问题为RestSharp WebAPI客户端创建一般错误处理程序。鉴于这些扩展方法:

I encountered this same problem while trying to create a generic error handler for a RestSharp WebAPI client. Given these extension methods:

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;
    }
}

我发出了一个请求,需要对反序列进行反序列化:

I made a request that required the response to be deserialized:

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 属性包含以下字符串:

However, during testing, I found that when I had no error handling configured for that case, my web serivce returned an HTML-formatted 404 page when an unmapped URL was requested. This caused the response.ErrorException property to contain the following string:


参考未申报的实体'nbsp'。第n行,位置m。

Reference to undeclared entity 'nbsp'. Line n, position m.

显然,RestSharp试图将响应解析为XML,即使内容类型是text / html 。也许我会为此向RestSharp提出一个问题。

As apparently RestSharp tried to parse the response as XML, even though the content-type was text/html. Maybe I'll file an issue with RestSharp for this.

当然在生产中你应该在拨打自己的服务时得到404,但我希望这个客户端是彻底和可重复使用。

Of course in production you should never get a 404 when calling your own service, but I want this client to be thorough and reusable.

所以有两个我能想到的解决方案:

So there's two solutions I can think of:


  • 检查状态代码并显示说明

  • 确保服务返回可以解析的错误对象

前者很容易完成。在 HandleErrorResponse()我根据状态代码的数值构建结果消息(用户可呈现)和错误字符串(loggable):

The former is done quite easily. In HandleErrorResponse() I build the result message (user presentable) and error string (loggable) based on the numeric value of the status code:

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 属性中的错误或异常消息的可解析响应模型:

Now as my API responses always are wrapped in a ResponseModel<T> of my making, I can set up an exception filter and a NotFound route to return a parsable response model with the error or exception message in the ResultMessage property:

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,我可以使用通用日志记录方法:

This way the response from my service can always be parsed by RestSharp, and I can use the generic logging method:

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

并记录 /的实际响应/(此处有其他错误处理),如果有的话:

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

这篇关于使用RestSharp时如何以惯用方式处理HTTP错误代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆