none
WebFaultException with HttpStatusCode.InternalServerError does not have an inner exception on the client RRS feed

  • Question

  • When I use HttpStatusCode.BadRequest in WebFaultException...

     

     throw new WebFaultException<CompositeType>(
      new CompositeType() { BoolValue = true, StringValue = "Opps3" },
      HttpStatusCode.BadRequest);
    

     

    on the client, the InnerException on the ProtocolException that is thrown has the HttpWebResponse.

     

      catch (ProtocolException ex)
      {
      throw; //ex.InnerException is WebException
      }
    

     

    However, when I use HttpStatusCode.InternalServerError

     

    throw new WebFaultException<CompositeType>(
      new CompositeType() { BoolValue = true, StringValue = "Opps3" },
      HttpStatusCode.InternalServerError);
    

     

    On the client, the CommunicationException that is thrown has no InnerException

    catch (CommunicationException ex)
      {
      throw; //ex.InnerException is null
      }

    What's going on in the client? Why is the innerexception null when the status code is InternalServerError?



    Sunday, April 10, 2011 4:37 AM

Answers

  • The problem is that Client stack treats HTTP error 500 different way than other errors.
    The same problem can be noticed in the Silverlight stack.
    Here you can find very similar problem, but related to Silverlight. To solve this I had implemented so called WCF - FaultCorrector behavior, which basically replaces error code 500 with 200. The behavior can be downloaded here.
    Please see if this works for you.


    Damir Dobric
    http://developers.de/members/ddobric/default.aspx
    http://www.daenet.de
    http://www.daenet.com
    http://www.daenet.eu
    • Marked as answer by Yi-Lun Luo Friday, April 15, 2011 9:02 AM
    Monday, April 11, 2011 9:09 PM

All replies

  • Hi

    Usually when the service throws WebFaultException the client will have to handle FaultException. Assume, we have a service like this:

    public class Service1 : IService1{

            public void DoWork()

            {

                throw new WebFaultException(System.Net.HttpStatusCode.BadRequest);

            }

        }

     

    After exception is thrown with BadRequest, this is what IIS/WCF will return to client:

    HTTP/1.1 500 Internal Server Error
    Content-Length: …
    Content-Type: text/xml; charset=utf-8
    Server: Microsoft-IIS/7.5
    X-Powered-By: ASP.NET
    Date: …

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/2009/WebFault">a:BadRequest</faultcode><faultstring xml:lang="de-DE">Bad Request</faultstring></s:Fault></s:Body></s:Envelope>

    In a case of InternalServerError following will be returned to client:

    HTTP/1.1 500 Internal Server Error
    Content-Length: …
    Content-Type: text/xml; charset=utf-8
    Server: Microsoft-IIS/7.5
    X-Powered-By: ASP.NET
    Date: …

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/2009/WebFault">a:InternalServerError</faultcode><faultstring xml:lang="de-DE">Internal Server Error</faultstring></s:Fault></s:Body></s:Envelope>

    As you see there is no any semantic difference. The server HTTP return code is in both cases 500. In both cases client will fail with regular FaultException. Digging in the Fault-Reason you can find out what has happened.

    The case which you describe happen in fact when the client cannot connect to service for any reason. In this case server will return following:

    HTTP/1.1 502 xxx - Connection Failed
    Content-Type: text/html
    Connection: close
    Timestamp: 17:54:09.497

    Connection to hostname failed…
    In this case HTTP error code is 502. This causes WCF at the client side to throw Protocol Exception.

    At the end, I would recommend you to decorate your operation contract with your own fault and handle it properly at the client.

     


    Damir Dobric
    http://developers.de/members/ddobric/default.aspx
    http://www.daenet.de
    http://www.daenet.com
    http://www.daenet.eu
    Sunday, April 10, 2011 4:10 PM
  • Some more details...

    1. The service is a WCF REST service.
    2. The operation contract is defined as follows:
          [OperationContract]
          [WebGet(RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json,UriTemplate = "contract/{contract}")]
          CompositeType GetDataUsingDataContract(string contract);
      
    3. Here's the client code:
       try
      {
         Service1Client client = new Service1Client();
         client.GetDataUsingDataContract("test");
      }
      
    4. Here's is all that the service does:
      throw new WebFaultException<CompositeType>(
              new CompositeType() { BoolValue = true, StringValue = "Opps3" },
              HttpStatusCode.BadRequest);
      
    5. Using Fiddler, here's what is returned for HttpStatusCode.BadRequest:

      HTTP/1.1 400 Bad Request

      Server: Microsoft-IIS/5.1

      Date: Mon, 11 Apr 2011 15:02:45 GMT

      X-Powered-By: ASP.NET

      X-AspNet-Version: 4.0.30319

      Content-Length: 41

      Cache-Control: private

      Content-Type: application/json; charset=utf-8

      {"BoolValue":false,"StringValue":"Opps3"}

    6. The exception on the client is a ProtocolException
      catch (ProtocolException ex)
      {
         throw;
       }
      
    7. The InnerException contains the HttpWebResponse so I can grab the exception details (CompositeType) by getting to the Response stream.
    8. Using Fiddler, here's what is returned for HttpStatusCode.InternalServerError:
      HTTP/1.1 500 Internal Server Error
      Server: Microsoft-IIS/5.1
      Date: Mon, 11 Apr 2011 14:58:24 GMT
      X-Powered-By: ASP.NET
      X-AspNet-Version: 4.0.30319
      Content-Length: 41
      Cache-Control: private
      Content-Type: application/json; charset=utf-8
      
      {"BoolValue":false,"StringValue":"Opps3"}
    9. The exception on the client is a CommunicationException
      catch (CommunicationException ex)
      {
         throw;
      }
      
      
    10. However, the InnerException is null so I cannot get to the response stream to grab the details. You can see from Fiddler that the exception details are actually part of what the WCF service is returning but on the client, I get nothing.
    Monday, April 11, 2011 3:07 PM
  • The problem is that Client stack treats HTTP error 500 different way than other errors.
    The same problem can be noticed in the Silverlight stack.
    Here you can find very similar problem, but related to Silverlight. To solve this I had implemented so called WCF - FaultCorrector behavior, which basically replaces error code 500 with 200. The behavior can be downloaded here.
    Please see if this works for you.


    Damir Dobric
    http://developers.de/members/ddobric/default.aspx
    http://www.daenet.de
    http://www.daenet.com
    http://www.daenet.eu
    • Marked as answer by Yi-Lun Luo Friday, April 15, 2011 9:02 AM
    Monday, April 11, 2011 9:09 PM