13

I'm using System.Net.WebRequest to get info from some API. When I get an error, the response contains only the basic HttpStatusCode and message, and not the full error returned. For comparison, running the same post data and headers in a tool such as POSTMAN will return the full error from that API.

I'm wondering if there is some property or way I can get the full error response??

Here is the code i'm running:

public HttpStatusCode GetRestResponse(
    string verb,
    string requestUrl,
    string userName,
    string password,
    out string receiveContent,
    string postContent = null)
{
    var request = (HttpWebRequest)WebRequest.Create(requestUrl);
    request.Method = verb;

    if (!string.IsNullOrEmpty(userName))
    {
        string authInfo = string.Format("{0}:{1}", userName, password);
        authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
        request.Headers.Add("Authorization", "Basic " + authInfo);
    }

    if (!string.IsNullOrEmpty(postContent))
    {
        byte[] byteArray = Encoding.UTF8.GetBytes(postContent);
        request.ContentType = "application/json; charset=utf-8";
        request.ContentLength = byteArray.Length;
        var dataStream = request.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();
    }

    try
    {
        using (WebResponse response = request.GetResponse())
        {
            var responseStream = response.GetResponseStream();
            if (responseStream != null)
            {
                var reader = new StreamReader(responseStream);
                receiveContent = reader.ReadToEnd();
                reader.Close();

                return ((HttpWebResponse) response).StatusCode;
            }
        }
    }
    catch (Exception ex)
    {
        receiveContent = string.Format("{0}\n{1}\nposted content = \n{2}", ex, ex.Message, postContent);
        return HttpStatusCode.BadRequest;
    }

    receiveContent = null;
    return 0;
}

When I generate a request that presents me with an error, I get in the error message: The remote server returned an error: (400) Bad Request. and no InnerException, and nothing else I can benefit from out of the exception.

[Answer] @Rene pointed to the right direction and the proper response body can be acquired like this:

var reader = new StreamReader(ex.Response.GetResponseStream());
var content = reader.ReadToEnd();
AlexD
  • 4,062
  • 5
  • 38
  • 65

1 Answers1

12

You're catching the generic exception so there is not much room for specific info.

You should catch the specialized exception that is thrown by the several webrequest classes, namely WebException

Your catch code could be like this:

catch (WebException e)
{
    var response = ((HttpWebResponse)e.Response);
    var someheader = response.Headers["X-API-ERROR"];
    // check header

    if (e.Status == WebExceptionStatus.ProtocolError)
    {
        // protocol errors find the statuscode in the Response
        // the enum statuscode can be cast to an int.
        int code = (int) ((HttpWebResponse)e.Response).StatusCode;
        string content;
        using(var reader = new StreamReader(e.Response.GetResponseStream()))
        {
            content = reader.ReadToEnd();
        }
        // do what ever you want to store and return to your callers
    }
}

In the WebException instance you also have access to the Response send from the host, so you can reach anything that is being send to you.

rene
  • 41,474
  • 78
  • 114
  • 152
  • This was actually the catch before I started meddling with it. I still can't see how I get the API-specific response that way. I've searched the object and searched again and can't find anything that's relevant – AlexD Aug 24 '15 at 06:41
  • I've added how you can inspect the other stuff. maybe you could share what postman shows, so that I understand what you're looking for. – rene Aug 24 '15 at 08:50
  • Here is the response I'm getting in POSTMAN: http://pastebin.com/uDRDesd7 and here is the headers collection: http://pastebin.com/FVzd7kWS – AlexD Aug 24 '15 at 08:59
  • Actually I tried reading the ConnectStream like this: `new StreamReader(((((HttpWebResponse)ex.Response))).m_ConnectStream).ReadToEnd()` and it seems to do the trick. I'll update in a moment – AlexD Aug 24 '15 at 09:01
  • 2
    `var reader = new StreamReader(ex.Response.GetResponseStream()); var content = reader.ReadToEnd();` Works well :) Thanks! – AlexD Aug 24 '15 at 09:14