Handling SOAP faults with HttpWebResponse object

When you call web services, in normal cases you would use the web service proxy objects that gets generated when you add a web reference and not send in an HTTP POST to the web service. I had an interest case recently where we had to build a test client that accepted invalid SOAP requests with malformed XML as well as well-formed SOAP requests.

If the web service returns a normal response, we can handle the response and just parse the returned XML. The code is what you would expect

 
try
{

WebResponse webResponse = webRequest.GetResponse();

if (webResponse != null)
{
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
response = sr.ReadToEnd().Trim();
}
}
catch (Exception ex)
{
// Handle the request
}


However, if the web service throws a SOAP fault when we try to get the response, the stack trace of the exception will not return the SOAP fault that you would expect. Instead we just a fairly generic error message and an HTTP 500 Internal Server error.



What's going on? If we use a HTTP sniffer to see the actual raw response we get some clues.
 
HTTP/1.1 500 Server Error
Server: Sun-ONE-Web-Server/6.1
Date: Wed, 15 Apr 2009 00:42:33 GMT
Content-length: 978
Content-type: text/xml; charset=utf-8
X-Powered-By: Servlet/2.4 JSP/2.0
X-Charles-Received-Continue: HTTP/1.1 100 Continue

 
soapenv:ServerSchema validation failed for request.5
Schema validation failed for request.
string value 'MVP_CUSTOMER' is not a valid enumeration value for CustomerType in namespace
http://acme.com/ws/customerorder/v1
MVP_CUSTOMER





It's apparent that the web server interprets a SOAP fault as an HTTP 500 error so it has nothing to do with HttpWebResponse class doing something invalid. When we sniffed the HTTP traffic, we could see the detailed SOAP fault information so why can't see it when we catch an exception?

We need to catch a WebException and then cast the WebException.Response into an HttpWebResponse object. Once we have a valid HttpWebResponse object, we can read the response stream and get the SOAP fault information out. We can then extract the information and turn it into a useful error messages for the logfile or the users.

 
try
{

WebResponse webResponse = webRequest.GetResponse();

if (webResponse != null)
{
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
response = sr.ReadToEnd().Trim();
}
}

catch (WebException wex)
{
// We issued an HttpWebRequest, so the response will be an
// HttpWebResponse.
HttpWebResponse httpResponse = wex.Response as HttpWebResponse;

// Grab the response stream.
using (Stream responseStream = httpResponse.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
// Grab the body of the response as a string for parsing.
string failureReason = reader.ReadToEnd();

// If it failed with a SOAP fault, parse the response body into a usable exception.
ThrowIfSoapFault(failureReason);

// If it was not a SOAP fault, rethrow the original exception.
throw;
}
}

}



Most of the code shown in this example can be found at MSDN.

  1. gravatar

    # by Igor - January 22, 2010 at 5:58 PM

    Many thanks.

  2. gravatar

    # by Anonymous - July 3, 2010 at 8:39 AM

    Thanks for this...

    One article on the entire web addressing this issue, makes me wonder who is developing what. As usual Microsoft makes it difficult to get any work done.

    --jl

  3. gravatar

    # by Anonymous - December 8, 2010 at 3:58 PM

    I was just about to throw my hands up and call the developer of the service a moron when I found this. This post turned a bad day into a good one! Thanks!

  4. gravatar

    # by Anonymous - December 19, 2011 at 7:32 AM

    Thanks you, Thank you, Thank you i have been going mad and this really helped.

  5. gravatar

    # by Anonymous - March 10, 2015 at 9:12 AM

    Great job, and thanks for sharing the experiment, too :) You saved me a 'notPossibleException' :D
    I started to be really annoyed .NET itself after System.Web.Services.Protocols.SoapException hadn't revealed anytheng even the SOAP service worked fine in another app.

  6. gravatar

    # by James NIOX - July 11, 2015 at 2:27 PM

    Hello,
    this article is really great !!!
    It saved me a lot or research and troubleshouting.

    You're awsome