WCF: Text Message Encoding and ISO-8859-1 Encoding

I’m a newbie in WFC and, so far, only have done client code to call POX web services.

I’ve been using a textMessageEncoding binding extension with a message version of None and a write encoding of utf-8 and all has been running fine.

Well, until I needed to call a service in iso-8859-1 encoding. Then I started getting a ProtocolException:

The content type text/xml;charset=iso-8859-1 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.

Bruno directed me to a sample that looked promising. The sample works fine because it’s using the same binding extension in the server and in the client.

When I tried to use the customTextMessageBinding from the sample, I got this nice ProtocolException:

The content type text/xml;charset=iso-8859-1 of the response message does not match the content type of the binding (text/xml; charset=iso-8859-1). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly.

Looks kind of funny, doesn’t it?

It comes down to the fact that the base MessageEncoder class doing a string comparison on the content type.

To solve this, I’ve overriden the IsContentTypeSupported method and added an additional validadion when the base validation fails. This new validation only checks for the media type of the response and lets the XmlReader handle the encoding.

public override bool IsContentTypeSupported(string contentType)

{

    if (base.IsContentTypeSupported(contentType))

    {

        return true;

    }

    if (contentType.Length == this.MediaType.Length)

    {

        return contentType.Equals(this.MediaType, StringComparison.OrdinalIgnoreCase);

    }

    else

    {

        if (contentType.StartsWith(this.MediaType, StringComparison.OrdinalIgnoreCase)

            && (contentType[this.MediaType.Length] == ‘;’))

        {

            return true;

        }

    }

    return false;

}

Since this seems to be happening in Orcas too, I’ve added a comment to the sample documentation and opened an issue. Vote on them.

21 thoughts on “WCF: Text Message Encoding and ISO-8859-1 Encoding”

  1. where do we override this method, in the application. is it in the client side or in the service side.

  2. So, this all makes sense to me, but for one thing: How do you configure your app to use your custom encoder containing the override?

  3. Read the article, but still don’t understand how easy I can implement this message encoder while calling such a webservice. Anyone any help?

  4. It’s probably since I’m not yet familiar enough with .Net/WCF ;-)

    But if I look at the artice I would have to write code for a custom MessageEncoder (where the IsContentTyepSupported is overridden), a custom
    MessageEncoderFactory and a custom TextMessageEncodingBindingElement?

    And I still cannot see where the custom MessageEncoder is actually hooked in when the call to the webservice is made.

  5. You have to do all that in order to WCF use your message encoder.

    The message encoder will be called in by WCF while WCF runs the request/response through its pipeline.

  6. Thought WCF was there to make our lifes easier ;-)

    For the moment fixed the problem at the other side: changed the PHP webservice so it returns UTF-8 and now it works.

    I’ll try to look at writing my own custom message encoder later.

    Thanx for your reponse, made things clearer for me!

  7. You are better of that way, but, at the time, I wasn’t allowed that luxury.

    Based on the sample, I wrote my onw message encoder and registered it and it without any change in both caller and called applications.

    <?xml version=”1.0″?>
    <configuration>
     <system.serviceModel>
       <bindings>
         <customBinding>
           <binding name=”MyCustomBinding”>
             <customTextMessageEncoding messageVersion=”None” writeEncoding=”ISO-8859-1″ mediaType=”text/xml” />
             <httpTransport manualAddressing=”false” keepAliveEnabled=”false” />
           </binding>
         </customBinding>
       </bindings>
       <client>
         <endpoint name=”MyServiceEndpoint”
             address=http://myserver/MyPoxEndpoint
                     contract=”IMyService”
                     binding=”customBinding”
                     bindingConfiguration=”MyCustomBinding” />
       </client>
     </system.serviceModel>
    </configuration>

  8. Paul,
    In the WSD Scan Spec, to retrieve a scan you send a standard utf-8 text message and recieve a mime type with enbedded MTOM in it. Since a basic wcf message can only send and recieve one type, could you use this to trap the content type mismatch? if so, without a custom message encoder can you use a IsContentTypeSupported overide and trap the mismatch?

    Thanks in advance,
    Eric

  9. Hi Eric,

    I’m not that good on WCF, but I think it could be done.

    IsContentTypeSupported is a member of the MessageEncoder class. So you need one to override it.

  10. I got this error too when using .NET 3.5/VS 2008. I added a “Service Reference” and imported the WSDL for a site driven by PHP. It built fine, but got the ISO-8859-1 encoding error.

    I tried again after changing the project properties to uses .NET 2.0. This time, I was not offered the option of adding a “Service Reference”, but I could add a “Web Reference”. When I did that, everything worked fine.

    Finally, I tried using .NET 3.5 again. I used “Add Service Reference” again, but this time I hit the “Advanced…” button. The next dialog box had a compatibility option where a button allowed you to add a “Web Reference” based on .NET 2.0 Web Services. This worked the same as when using .NET 2.0, but the rest of your app can use .NET 3.5.

    There must be advantages in using the “Service Reference”, but until WCF supports ISO-8859-1, using a “Web Reference” beats having to override IsContentSupported.

  11. I agree that WCF should support other encodings, but if you need something more than just calling a web service (security, other bindings (TCP, Pipes, etc.), logging, tracing, etc.) nothing beats WCF.

  12. I’ve tried to implement that example but there is something I think I’m missing. The type attribute in setting up binding extension-

    <add name=”X” type=”Y” /> — What does it means? I thought it was formed: [namespace, customMessageEncoderClassName] but it shows runtime error no being available to find the type Y registered to extension X. I want to find Y!!!

  13. Well I think I finally understood. I thought just MessageEncoder and MessageEncoderFactory were needed and it seems that I need BindingElement and EncodingElement too.

    The type attribute seems to be [encodingElementClassName, assemblyName]. I found a libary with multiple encoding support at developers.de/…/custom-message-encoding.aspx I hope it helps.

  14. Did you ever experience an issue where, after changing the encoding on the binding to ISO-8859-1 with the custom binding, you get the following?

    The message with Action ” cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

  15. I can’t say I have, but I haven’t been playing with this stuff for a long time.

    Have you tried something like Fiddler to see what goes on the wire for a successful and unsuccessful call?

Comments are closed.