Based upon a user request, I'll explain why wsDualHttpBinding(a system-provided binding in WCF) is not an interoperable binding. This blog entry will explain the service endpoint code, client code, generated WSDL and the SOAP messages exchanged based upon the DualHttp Binding Sample that is bundled with the Windows SDK samples. This is also an update to an earlier attempt to explain wsDualHttpBinding.


In the sample, I replaced the default wsDualHttpBinding with an equivalent custom binding (after removing the security) as:

    <binding name="Binding1">
      <reliableSession />
      <compositeDuplex />
      <oneWay />
                     writeEncoding="utf-8" />
      <httpTransport authenticationScheme="Anonymous"
                     useDefaultWebProxy="true" />

The wsDualHttpBinding, also known as Composite Duplex orFull Duplex Binding, provides a bi-directional communication between Client and Endpoint. In a single direction communication, the client can invoke a set of operations on a service and this interface is referred as primary interface in Duplex binding. The set of operations that a service can invoke on the client is called as callback interface.

The sample in Windows SDK is a trivial calculator service where primitive Math operations are performed in a running session on the "primary" interface and results are returned on the "callback" interface.

Service Endpoint Code

Let's understand the service endpoint code first. The "primary" service endpoint interface looks like:

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples",                 SessionMode=SessionMode.Required,
public interface ICalculatorDuplex
  void Clear();
  [OperationContract(IsOneWay = true)]
  void AddTo(double n);


Three points to note in this code:

  • A duplex contract requires a session, because a context must be established to correlate the set of messages being sent between client and service. Even though this is specified usingSessionMode=SessionMode.Required attribute but the default value of SessionMode=SessionMode.Allowed(equivalent of not specifying) will be sufficient as well. This is because all Duplex bindings in .NET maintain a transport session.

  • Callback interface is specified usingCallbackContract attribute.

  • All the methods are declared as One-way operations otherwise the response can be returned on the transport back channel itself. The documentation on this particular binding is limited.

The "callback" interface is defined as:

public interface ICalculatorDuplexCallback
  [OperationContract(IsOneWay = true)]
  void Result(double result);


In order for a service endpoint to establish a connection with the "callback" interface on client, a CallbackChannelis obtained from the OperationContext in the implementation of the "primary" interface as:

public class CalculatorService : ICalculatorDuplex
  double result;
  ICalculatorDuplexCallback callback = null;

  public CalculatorService()
    result = 0.0D;
    callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();

Another variable is initialized to return the running result. The implementation of each method in the "primary" interface then invokes a method on the "callback" interface to return the running result as:

public void AddTo(double n)
  result += n;

Generated WSDL

Now let's look at the generated WSDL fragments. The policy assertion elements are:

  <wsrm:RMAssertion xmlns:wsrm="">
    <wsrm:InactivityTimeout Milliseconds="600000" /> 
    <wsrm:AcknowledgementInterval Milliseconds="200" /> 
 <cdp:CompositeDuplex xmlns:cdp="" /> 
  <ow:OneWay xmlns:ow="" /> 
  <wsaw:UsingAddressing /> 

The wsrm:RMAssertion andwsaw:UsingAddressing elements are bound to a known namespace and their behavior is clearly documented. However the specification ofcdp:CompositeDuplex and ow:OneWayelements are unclear at this time. This does not allow any WSDL-based interoperability whenever these elements are included.

All methods from the "primary" and the "callback" interface are generated in one wsdl:portType. The methods from the "primary" interface are generated as One-way operations. But methods from the "callback" interface are generated as Notification operation. For example, one of the methods from "callback" interface looks like:

<wsdl:operation msc:isInitiating="true" msc:isTerminating="false" name="Result">

JAX-WS, the core of Metro, supports only Request-Responseand One-wayoperations. This is the second place where WSDL-based interoperability will not work with any JAX-WS-based WSDL import tool, such as wsimport. Moreover, the WSDL-to-Java mapping defined by the JAX-WS specification requires each wsdl:portType map to a single Java interface. This WSDL design pattern requires two interfaces to be generated from a singlewsdl:portType.

There are some other elements in namespace prefix bound to "" and their purpose is also unclear. Rest of the WSDL is pretty straight-forward.

Client side code

On the client side, svcutil (WSDL importing tool for .NET 3.0) generates the "primary" and "callback" interface from the WSDL. The "callback" is implemented as:

public class CallbackHandler : ICalculatorDuplexCallback
  public void Result(double result)
    Console.WriteLine("Result({0})", result);

  public void Equation(string eqn)
    Console.WriteLine("Equation({0})", eqn);

This client instance is initialized with the callback implementation as:

class Client
  static void Main()
    // Construct InstanceContext to handle messages on callback interface
    InstanceContext instanceContext = new InstanceContext(new CallbackHandler());

    // Create a client with given client endpoint configuration
    CalculatorDuplexClient client = new CalculatorDuplexClient(instanceContext);

And then the client invokes the service endpoint normally as shown below:

// Call the AddTo service operation.
double value = 100.00D;


SOAP messages

Lets look at the SOAP messages exchanged between client and endpoint now. The first call from the client to an endpoint triggers a protocol handshake for establishing a session. TheCreateSequence protocol message looks like:

<s:Envelope xmlns:s="" xmlns:a="">
    <a:Action s:mustUnderstand="1"></a:Action>
    <a:To s:mustUnderstand="1">http://localhost:8888/</a:To>
    <CreateSequence xmlns="">

The WCF runtime uses the Windows HTTP.SYS library to host an endpoint at the address specified in a:ReplyTo. This address is used for all subsequent messages sent on the callback channel. This message is used to create a session for the "primary" interface. The message also carries an offer, in the SOAP Body, to create a "callback" interface session.

The CreateSequenceResponse protocol message returns "primary" interface session identifier and also accepts the offered "callback" session. The message looks like:

<s:Envelope xmlns:s="" xmlns:a="">
    <a:Action s:mustUnderstand="1"></a:Action>
    <a:To s:mustUnderstand="1"></a:To>
    <CreateSequenceResponse xmlns="">

Now, because of the way each method is implemented (invokingcallback.Result(result) method at the end of each "primary" operation), a response to a request received by an endpoint is returned over the callback channel. This happens under-the-cover even though all messages in the "primary" interface are defined as One-way operations.

The behavior is quite analogous to a Request-Response operation primitive. I wonder what are the usecases of wsDualHttpBinding ?


Finally, I summarize the reasons that makes wsDualHttpBinding a non-interoperable binding:

  1. The specifications of cdp:CompositeDuplex andow:OneWay are not available and these elements will thus be ignored by the Metro WSDL importing tool.

  2. The operations from "callback" interface are mapped as Notification operation in the WSDL. This operation primitive is not supported by Metro.

  3. On the service endpoint, all the operations from "primary" and "callback" interface are mapped to a singlewsdl:portType. On the client side, wsdl:portType is mapped to separate "primary" and "callback" interfaces. The Java-to-WSDL mapping defined by the JAX-WS specification allows one-to-one mapping between Java interface andwsdl:portType.

Technorati: webservices interoperabilitywcf projectmetro jax-ws wsit