4

I have a WCF service, which has a method with the following signature:

object GetCommand(Guid apiKey, SocialService service, string name, object argument);

The reason it's working with objects as both the return type and last argument, is because it should be possible to pass any type as argument and return any type.

Anyway, I'm passing an object, which contains the following property:

public byte[] Photo { get; set; }

To enable large messages, I'd like to start using Mtom, while I was previously using plain-text as MessageEncoding type.

Problem is, I want it to be backwards compatible, so current already-configures clients should keep using plain-text encoding, while new clients should be able to use Mtom via the web.config.

My question is: is it possible to keep using plain-text as MessageEncoding by default (existing clients) and offer Mtom encoding as well side-by-side?

I've tried some things with the configuration, like defining multiple endpoints with different binding-configurations, but I can't get it to work:

Server

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpTextBinding_SocialProxy" />
            <binding name="BasicHttpMtomBinding_SocialProxy" maxReceivedMessageSize="5242880" messageEncoding="Mtom">
                <readerQuotas maxStringContentLength="655360" maxArrayLength="1310720" maxNameTableCharCount="1310720" maxBytesPerRead="327680" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <services>
        <service name="SocialProxyService">
            <endpoint name="BasicEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpTextBinding_SocialProxy" />
            <endpoint name="MtomEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpMtomBinding_SocialProxy" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="true" />
                <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

Client

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_SocialProxy" messageEncoding="Mtom" />
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://socialproxy.local/socialproxy.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SocialProxy"
            contract="Webservice.SocialProxy" name="BasicHttpBinding_SocialProxy" />
    </client>
</system.serviceModel>

Problem is:

If I don't set Mtom messageEncoding @ the client, everything works via plain-text. But when I set it to use Mtom, I'll get an exception:

The remote server returned an error: (415) Cannot process the message because the content type 'multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:65a6b418-8eb3-4c76-b4c0-ea3486a56892+id=2";start-info="text/xml"' was not the expected type 'text/xml; charset=utf-8'..

Anyone able to help me out? :-)

kipusoep
  • 2,174
  • 6
  • 24
  • 34

1 Answers1

4

If you want to add a new endpoint (for newer clients), that endpoint needs to be in a different address. Since you didn't get any error, I imagine you have an incorrect name in the name attribute of the <service> element. Remember that the name attribute should contain the fully-qualified name of the service class. If your service class is at the namespace InfoCaster.SocialProxy, your service configuration should be defined like below:

<services> 
    <service name="InfoCaster.SocialProxy.SocialProxyService"> 
        <endpoint name="BasicEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpTextBinding_SocialProxy" /> 
        <endpoint name="MtomEndpoint_SocialProxy" address="newClients" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpMtomBinding_SocialProxy" /> 
    </service> 
</services> 

And the clients would have something like

<client>  
    <endpoint address="http://socialproxy.local/socialproxy.svc/newClients"  
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SocialProxy"  
        contract="Webservice.SocialProxy" name="BasicHttpBinding_SocialProxy" />  
</client>  

Now, if you want a single endpoint which can support both text and MTOM in a way that clients sending text receive a text response, and clients which send MTOM receive a MTOM response back, you can still do it. You'll need a custom encoder, and I wrote one in the post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/02/16/using-mtom-in-a-wcf-custom-encoder.aspx.

carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
  • Thanks for the reply. If I understand correctly, it's impossible to support both encoding types for the same address? That would be a real pity! I'll have a go with your solution tomorrow and post back when done. – kipusoep Apr 12 '12 at 20:14
  • You can, but it's not as straightforward. I've updated the answer with more details. – carlosfigueira Apr 12 '12 at 22:29
  • Thanks a lot Carlos! I'm kind of a noob when it comes to WCF and custom message encoders. Problem is; I have taken the code pieces from your blogpost, but I'm still missing some parts. Also I've found this forum thread; http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/f5c0ea22-1d45-484e-b2c0-e3bc9de20915/ and there is a c# file mentioned there, but it's not available. So the current problems I have is implementing the ContentType, MediaType and MessageVersion properties. Also I'm missing a class called 'TextOrMtomEncodingBindingElement'. Here's the code: http://pastebin.com/jxk3WeJX – kipusoep Apr 13 '12 at 07:47
  • Omg, I just saw the link at the bottom of your blogpost to the source, will check it out right now :-) – kipusoep Apr 13 '12 at 08:06
  • So after digging around a lot I've finally got it working. Thanks alot Carlos! :-) – kipusoep Apr 13 '12 at 11:33