0

I have a c# application that sends requests to several API's, but earlier today one of them seemed to be down for a while and caused an exception within my exception handler:

catch (WebException e)
{
    var statusCode = ((HttpWebResponse)e.Response).StatusCode;
    //Use status code and exception for reporting and handling.
}

This caused a problem because at the time, the Exception did not have a Response, so I was trying to get the StatusCode of nothing, and a NullPointerException was thrown.

I've since changed it to this in order to try and get the status code if there's no response (I didn't use the response for anything other than the status code anyway).

catch (WebException e)
{
    //Try to get the status code from the exception, can fail somehow.
    HttpStatusCode statusCode;
    try
    {
        statusCode = (HttpStatusCode)e.Status;
    }
    catch(Exception innerE)
    {
        //Capture exceptions for logging
        //...
        //Set a default code to continue.
        statusCode = HttpStatusCode.InternalServerError;
    }
    //Use status code and exception for reporting and handling.
}

From this answer it looks like you can try for both the status from the response and the status from the exception.

My question is if I should try for both or if one would be set over another?

For example, in order to test the code I'm using now, I was able to manually throw a WebException with just the status and no response.

Could there be any instance where I'd get a response with no status on the exception? Or if there could be a situation where the status code from the response would be more detailed or different from the status code straight from the exception itself?

I am making the call with a basic HttpWebRequest.

Update:

The API that I interact with I don't have control over and it wasn't until the failure happened today that I found out it was possible to come back with no response. I set it manually to the 500 for my own error handling further down in the catch block, my users don't know that's what I use. I'm just asking if one way of retrieving the StatusCode is better/different than another way. Or if I shouldn't rely on one method over another, and if I should try both and which to prefer?

Community
  • 1
  • 1
Alec Gordon
  • 195
  • 4
  • 10

2 Answers2

1

My processing of similar situations would be to try and get as much from the remote server as I could, if possible. And if there was no response, the catch would assign a status code manually.

The problems come in when you start sending various codes back, particularly 5xx series server errors. I don't like returning their 500 as a problem which is mine.

In the long run, caught Web Exceptions would just get logged into an ApiError table, and I would return what I felt was the most appropriate response code, falling back to 408 or if no response I would send back the non-standard 444 code for "No Response".

That is the beauty of error handling; you catch an error, do the best you can, and can convert to a standardized HTTP status.

Mad Myche
  • 1,040
  • 1
  • 7
  • 15
  • The API that I interact with I don't have control over and it wasn't until the failure happened today that I found out it was possible to come back with no response. I set it manually to the 500 for my own error handling further down in the catch block, my users don't know that's what I use. I'm just asking if one way of retrieving the StatusCode is better/different than another way. Or if I shouldn't rely on one method over another, and if I should try both and which to prefer? – Alec Gordon May 19 '17 at 19:30
  • What you have is fine with the try-catch-try, I just don't report the errors of others as a 500, I'll go with a No Response and let the end user we could not validate .... – Mad Myche May 19 '17 at 19:41
1

I have the same problem and I realise a few things while I search for a solution.

  • WebExceptionStatus enum is not equivalent to http status code that the API you call returned. Instead it is a enum of possible error that may occour during a http call.
  • The WebExceptionStatus error code that will be returned when you receive an error (400 to 599) from your API is WebExceptionStatus.ProtocolError aka number 7 as int.
  • When you need to get the response body or the real http status code returned from the api, first you need to check if WebExceptionStatus.Status is WebExceptionStatus.ProtocolError. Then you can get the real response from WebExceptionStatus.Response and read its content.

This is an example:

try
{
    ...
}
catch (WebException webException)
{
    if (webException.Status == WebExceptionStatus.ProtocolError)
    {
        var httpResponse = (HttpWebResponse)webException.Response;
        var responseText = "";
        using (var content = new StreamReader(httpResponse.GetResponseStream()))
        {
            responseText = content.ReadToEnd(); // Get response body as text
        }
        int statusCode = (int)httpResponse.StatusCode; // Get the status code
    }

    // Handle other webException.Status errors
}
Lutti Coelho
  • 1,610
  • 11
  • 23