1

I'm testing out faults and exception handling on my service and am seeing odd results.

I have one service contract that has two endpoints configured. One is basicHttpBinding and the other is wsHttpBinding. Locally on my machine I have a test app client and server running. I can call both web service bindings successfully and get the exception I'm looking for on both, exactly what I'm looking for. But when I push my code out to the dev server I can only call the wsHttpBinding endpoint successfully. The basic endpoint returns an odd message. The exception is "The remote server returned an error: (500) Internal Server Error."

and the Exception Message is:

"The content type text/html of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: insert bunch of nonsense html here"

Is this a configuration error? An IIS error? A firewall issue? I've ran WCF logging and also tracing on the server. My code is being hit just fine and it's throwing a fault exception fine. The Message Header is empty on the basicHttpBinding but I'm not sure if that's a problem. I've checked the IIS logs as well. It shows the 500 errors but that's all. Is there anything else I should check?

My endpoints:

<endpoint 
 address="" 
 binding="wsHttpBinding" 
 bindingConfiguration="WSHttpBinding_IEOIEligible_NONSSL"
 name="IEOIEligible_Svc_endpoint_NONSSL" 
 contract="Engine.IEOIEligible">
</endpoint>

<endpoint 
address="mex" 
binding="mexHttpBinding" 
name="Mex_Svc_endpoint"
contract="IMetadataExchange" />

<endpoint 
    address="/basic" 
    binding="basicHttpBinding" 
    bindingConfiguration="BasicHttpBinding_IEOIEligible"
    name="basicEOIEndpoint" 
    contract="Engine.IEOIEligible" />

[Edit]

Binding configuration:

basicHttpBinding

<binding name="BasicHttpBinding_IEOIEligible" closeTimeout="00:01:00"
      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
      allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
      maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"
      messageEncoding="Text" textEncoding="utf-8" transferMode="Streamed"
      useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="None">
        <transport clientCredentialType="Certificate" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="Certificate" algorithmSuite="Default" />
      </security>
    </binding>

wsHttpBinding

<binding name="WSHttpBinding_IEOIEligible_NONSSL" closeTimeout="00:10:00"
      openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
                maxBufferPoolSize="524288" maxReceivedMessageSize="524288" messageEncoding="Text"
      textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
      <readerQuotas maxDepth="32" maxStringContentLength="819200" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00"
        enabled="false" />
    </binding>

From the WCF trace file:

The successful call (wsHttp):

<ExtendedData     xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/MessageTraceRecord">
 <MessageProperties>
  <Encoder>application/soap+xml; charset=utf-8</Encoder>
  <AllowOutputBatching>False</AllowOutputBatching>
 </MessageProperties>
 <MessageHeaders>
  <Action d4p1:mustUnderstand="1" xmlns:d4p1="http://www.w3.org/2003/05/soap-envelope" xmlns="http://www.w3.org/2005/08/addressing">http://tempuri.org/IEOIEligible/VerifyEOIRequiredEOIEligibilityFaultFault</Action>
 <RelatesTo xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:5863c107-b721-4b4c-88b8-0d03c22175d1</RelatesTo>
 <ActivityId CorrelationId="a498440c-2e5a-4298-9bc5-ade08d51933c" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000</ActivityId>
 </MessageHeaders>
</ExtendedData>

the server 500 (basicHttp)

<ExtendedData xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/MessageTraceRecord">
 <MessageProperties>
  <Encoder>text/xml; charset=utf-8</Encoder>
  <AllowOutputBatching>False</AllowOutputBatching>
 </MessageProperties>
 <MessageHeaders></MessageHeaders>
</ExtendedData>

[Edit]

I am able to get a response from the service using the basicHttpBinding via the Microsoft WCF Test Client but that's only when I don't throw a FaultException on the server, meaning the service returned down the happy path. This part I'm not concerned with, thankfully.

I'm unit testing client exception handling and the server is returning a 500 on the basic but not the wsHttpBinding. The wsHttpBinding is returning the proper SOAP fault embedded within the soap body but the basic isn't. The Soap fault is returned with basicHttpBinding when ran locally just not from a true server.

EbbnFlow
  • 653
  • 1
  • 9
  • 17
  • 1
    Can you add binding configurations to question? – Dmitry Harnitski Jun 20 '12 at 22:57
  • possible duplicate of: http://stackoverflow.com/questions/5243929/wcf-service-client-the-content-type-text-html-charset-utf-8-of-the-response-me – ErnieL Jun 21 '12 at 05:52
  • @dharnitski I added the binding configs. Thanks! – EbbnFlow Jun 21 '12 at 12:38
  • 1
    Can you use something like Fiddler to see what's the HTML page being returned on the call to the BasicHttpBinding? Also, instead of using message logging, try using WCF *tracing* (diagnostics), it should have more information about the error. – carlosfigueira Jun 21 '12 at 13:52

3 Answers3

2

I had the same error for my basicHttp endpoint. I figured out to change the encoding of my web.config from 'Ansi as utf8' to 'utf8'

backboner
  • 21
  • 3
1

I figured out the problem to my question. It was a simple config change (that took hours to find). In my binding I changed

transferMode="Streamed"

to

transferMode="Buffered"
EbbnFlow
  • 653
  • 1
  • 9
  • 17
1

I've been looking around for two days now, trying to find a solution and an explanation why my WCF service with custom SOAP Faults refused to work, IIS spitting out http 500 errors instead, with the same client side exception: "The content type text/html of the response message does not match the content type of the binding...".

The worst thing being it worked locally on IIS Express or using a ServiceHost instance!

Your answer greatly helped me diagnose and solve the problem, so thank you.

Here is my solution and explanation for anyone interested.


Normally, when using faults, the response to the client is a SOAP xml message (when using a text/xml message encoder) containing the error details.

Using Fiddler, I was able to intercept and see the responses sent back to the client in both buffered mode and streamed mode.

Here is the response message in buffered mode:

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
   <s:Header>
      <a:Action s:mustUnderstand="1">http://tempuri.org/ISIAdministration/MyServiceBusinessFaultFault</a:Action>
      <a:RelatesTo>urn:uuid:a6a89101-7d95-4e7b-9871-c43792559f16</a:RelatesTo>
   </s:Header>
   <s:Body>
      <s:Fault>
         <s:Code>
            <s:Value>s:Sender</s:Value>
         </s:Code>
         <s:Reason>
            <s:Text xml:lang="fr-FR">Le créateur de cette erreur n'a pas spécifié de raison.</s:Text>
         </s:Reason>
         <s:Detail>
            <BusinessFault xmlns="http://schemas.datacontract.org/2004/07/GI.Framework.Error" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
               <MyCode>test</MyCode>
               <MyMessage>test</MyMessage>
            </BusinessFault>
         </s:Detail>
      </s:Fault>
   </s:Body>
</s:Envelope>

And here is the response message in streamed mode:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>500 - Erreur interne au serveur.</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}
fieldset{padding:0 15px 10px 15px;} 
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} 
#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;
background-color:#555555;}
#content{margin:0 0 0 2%;position:relative;}
.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
-->
</style>
</head>
<body>
<div id="header"><h1>Erreur de serveur</h1></div>
<div id="content">
 <div class="content-container"><fieldset>
  <h2>500 - Erreur interne au serveur.</h2>
  <h3>La ressource que vous recherchez présente un problème, elle ne peut donc pas être affichée.</h3>
 </fieldset></div>
</div>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
   <s:Header>
      <a:Action s:mustUnderstand="1">http://tempuri.org/ISIAdministration/MyServiceBusinessFaultFault</a:Action>
      <a:RelatesTo>urn:uuid:a6a89101-7d95-4e7b-9871-c43792559f16</a:RelatesTo>
   </s:Header>
   <s:Body>
      <s:Fault>
         <s:Code>
            <s:Value>s:Sender</s:Value>
         </s:Code>
         <s:Reason>
            <s:Text xml:lang="fr-FR">Le créateur de cette erreur n'a pas spécifié de raison.</s:Text>
         </s:Reason>
         <s:Detail>
            <BusinessFault xmlns="http://schemas.datacontract.org/2004/07/GI.Framework.Error" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
               <MyCode>test</MyCode>
               <MyMessage>test</MyMessage>
            </BusinessFault>
         </s:Detail>
      </s:Fault>
   </s:Body>
</s:Envelope>

Notice anything strange?

For a reason I ignore, it seems IIS does not handle errors the same way for buffered or streamed responses, and it actually inserts the content of the custom 500 error page before the expected xml message!!!

IIS also changes the Content-Type of the response to text/html, which explains the exception message.

That's why switching from streamed messages to buffered ones fixed the problem in your case, but in my case this fix was not acceptable because I needed to transfer hundreds of megabytes of data.


Once I accepted the fact it was most probably a IIS bug, and not a configuration problem from my part, finding a solution was easy:

TL;DR:

The problem comes from the IIS custom error pages, so you just need to disable them for your service. This is done either from the IIS administration panel, or by adding a simple configuration directive to the web.config file, instructing IIS to let the existing fault messages pass through without altering them:

<system.webServer>
    <httpErrors existingResponse="PassThrough" />
</system.webServer>

And that's it!

Melvyn
  • 622
  • 10
  • 11