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 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;
}
}
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 has added boolean property
IRestResponse.IsSuccessful
which covers your use case. I couldn't find any documentation referring to this property, but here's the line that defines the property's method.Interesting to note is that RestSharp considers codes 200-299 to be successful, while CodeCaster considers codes 200-399 to be successful.
I encountered this same problem while trying to create a generic error handler for a RestSharp WebAPI client. Given these extension methods:
I made a request that required the response to be deserialized:
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: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.
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:
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: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 theResultMessage
property:And:
This way the response from my service can always be parsed by RestSharp, and I can use the generic logging method:
And log the actual response at
// (other error handling here)
, if available:It should be enough to check for a success code, and throw or report the error if you get any other code apart from success. This usually means checking for HTTP Status 200 after every request. If you create a new resource, you should expect Status 201.
With most APIs/frameworks, it is very very unusual to see any other status code except these if nothing has gone wrong.