Spaceman Spiff
Spaceman Spiff

Reputation: 934

Get data on error with HttpWebRequest

While interacting with an API there is a situation where they will return a 401 response that also contains data. I would like to return this data regardless of the error code of the response.

I have created a function to submit a either a GET or POST using HttpWebRequest that returns a string containing the response data. The only problem is that if the response is a 401, an error is thrown and the data is not read.

Here is an example of what is returned:

HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: false
Content-Type: application/json; charset=UTF-8
Date: Tue, 19 May 2015 17:56:10 GMT
Vary: Accept-Encoding
Vary: Accept-Encoding
Content-Length: 254
Connection: keep-alive

{"status":"error","message":"access_token (...) was deleted (at Tue May 19 17:52:49 UTC 2015).  Use your refresh token (if you have one) to generate a new access_token.","requestId":"..."}

Here is what I have for my function so far:

private string SendHttpRequest(string url, out int statusCode, string method = "GET", object postData = null, string contentType = "application/json")
{
    bool isPost = method.Equals("POST", StringComparison.CurrentCultureIgnoreCase);

    byte[] content = new ASCIIEncoding().GetBytes(isPost ? JsonConvert.SerializeObject(postData) : "");

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

    request.AllowAutoRedirect = true;
    request.Method = method;
    request.ContentType = contentType;
    request.ContentLength = postData == null ? 0 : content.Length;

    if (isPost && postData != null)
    {
        Stream reqStream = request.GetRequestStream();
        reqStream.Write(content, 0, content.Length);
    }

    HttpWebResponse response = (HttpWebResponse)request.GetResponse(); // Throws error here

    string result;

    using (StreamReader sr = new StreamReader(response.GetResponseStream()))
    {
        result = sr.ReadToEnd();
    }
    statusCode = (int)response.StatusCode;

    response.Close();

    return result;
}

How can I still get the data for a 401 response? There is no requirement to use HttpWebRequest, that is just what I have been using so far.

Upvotes: 2

Views: 2193

Answers (1)

p e p
p e p

Reputation: 6674

The call to GetResponse is throwing a WebException. You can catch that exception and extract the response via the exception's Response property:

private string SendHttpRequest(string url, out int statusCode, string method = "GET", object postData = null, string contentType = "application/json")
{
    bool isPost = method.Equals("POST", StringComparison.CurrentCultureIgnoreCase);

    byte[] content = new ASCIIEncoding().GetBytes(isPost ? JsonConvert.SerializeObject(postData) : "");

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

    request.AllowAutoRedirect = true;
    request.Method = method;
    request.ContentType = contentType;
    request.ContentLength = postData == null ? 0 : content.Length;

    if (isPost && postData != null)
    {
        Stream reqStream = request.GetRequestStream();
        reqStream.Write(content, 0, content.Length);
    }

    HttpWebResponse response = null;

    //Get the response via request.GetResponse, but if that fails,
    //retrieve the response from the exception
    try
    {
        response = (HttpWebResponse)request.GetResponse();
    }
    catch (WebException ex)
    {
        response = (HttpWebResponse)ex.Response;
    }

    string result;

    using (StreamReader sr = new StreamReader(response.GetResponseStream()))
    {
        result = sr.ReadToEnd();
    }
    statusCode = (int)response.StatusCode;

    response.Close();

    return result;
}

Upvotes: 3

Related Questions