WCF: Multiple binding configurations for a single service

John Russell picture John Russell · Jun 19, 2013 · Viewed 29.4k times · Source

I'm working on a client-server application (.NET 4 WPF, WCF) that must support backwards compatibility. In other words, old clients should be compatible with new servers (and vice versa) as far as operation contracts and data contracts.

Our WCF services are hosted in IIS, and they were set up to use basicHttpBinding:

<basicHttpBinding>
   <binding name="basicHttpBinding_Configuration" maxBufferSize="2147483647"
      maxReceivedMessageSize="2147483647">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
         maxArrayLength="2147483647" />
      <security mode="None" />
   </binding>
</basicHttpBinding>

...

<service behaviorConfiguration="SampleGateway.Data.DataAccessBehavior"
   name="SampleGateway.Data.DataAccess">
   <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_Configuration"
      contract="Sample.Data.IDataAccess" />
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      <host>
      <baseAddresses>
         <add baseAddress="http://localhost:8731/Design_Time_Addresses/SampleGateway/SampleGateway.Data.DataAccess.svc" />
      </baseAddresses>
   </host>
</service>

...

<behavior name="SampleGateway.Data.DataAccessBehavior">
   <serviceMetadata httpGetEnabled="true" />
   <serviceDebug includeExceptionDetailInFaults="false" />
   <dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>

Assume the contract is pretty basic and looks something like this:

[ServiceContract]
public interface IDataAccess
{
   [OperationContract]
   List<Data> GetData(List<int> ids, DateTime startDateTime, DateTime endDateTime);
}

Recently, I discovered that we could change our encoding from XML to binary. Combined with IIS compression, this really boosted the performance of our WCF methods such as GetData listed above.

This encoding change also required a change in the client and server WCF bindings, switching from a basicHttpBinding to a customBinding.

<customBinding >
   <binding name="binaryHttpBinding_Configuration">
      <binaryMessageEncoding maxReadPoolSize="2147483647" maxSessionSize="2147483647" maxWritePoolSize="2147483647">
         <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="2147483647"/>
      </binaryMessageEncoding>
      <httpTransport transferMode="Streamed" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" useDefaultWebProxy="true"/>
   </binding>
</customBinding>

...

<service behaviorConfiguration="SampleGateway.Data.DataAccessBehavior"
   name="SampleGateway.Data.DataAccess">
   <endpoint address="" binding="customBinding" bindingConfiguration="binaryHttpBinding_Configuration"
      contract="CEMLink.Data.IDataAccess" />
   <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
   <host>
      <baseAddresses>
         <add baseAddress="http://localhost:8731/Design_Time_Addresses/SampleGateway/SampleGateway.Data.DataAccess.svc" />
      </baseAddresses>
   </host>
</service>

...

Here's the problem. Since our software must support client/server backwards compatibility, if an old client with the old basicHttpBinding tries to hit a server with the new customBinding, the call is going to fail with a mismatch, e.g. "Content Type text/xml; charset=utf-8 was not supported by this service.... The client and service bindings may be mismatched"

Can I have two binding configurations for the same service contract - one basic and the other custom, and they both point to the same interface? How can I work around this?

Answer

Anu picture Anu · Jun 20, 2013

You basically need 2 endpoints for the same service exposed at different addresses and aligned with different bindings. This may help you.