I have been working on a WCF intermediary that receives messages from a 3rd party and routes this onto another WCF service. The intermediary service uses basicHttpBinding whereas the destination service is netTcpBinding. I have worked on similar patterns before, but they always had the same binding on each service and they worked well, therefore I hadn’t anticipated any problems.


However, once I had this all set-up I started receiving the following error on the intermediary service: “Addressing Version ‘AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)’ does not support adding WS-Addressing headers.”


This error appears to stem from the fact that basicHttpBinding is using SOAP 1.1 for the message version and no WS-Addressing, whereas netTcpBinding is using SOAP 1.2 for the message version with WS-Addressing. I had originally attempted to use custom bindings to get over this hurdle without much success so adopted to implement a message conversion in the intermediary service instead.


Your typical intermediary service would tend to have a service contract that is defined as so:


[ServiceContract]


public interface IMyIntermediaryService


{


   [OperationContract(


      IsOneWay = false,


      IsInitiating = true,


      IsTerminating = false,


      Action = “*”,


      ReplyAction = “*”)]


   [FaultContract(


      typeof(MyCustomFault),


      Namespace = “http://mydomain.com/myapplication/2009/08”)]


  


   Message ProcessMessage(Message message);


}


The implementation of the ProcessMessage method would be something like the following. Note that this is a very basic example to be succinct, you would need to include error handling etc. In addition we are defining the destination endpoint in the web.config using the name “destination” as the identifier.


public Message ProcessMessage(Message message)


{


   var channelFactory = new ChannelFactory<IMyIntermediaryService>(“destination”);


 


   IMyIntermediaryService forwardingChannel = channelFactory.CreateChannel();


 


   Message responseMessage = forwardingChannel.ProcessMessage(message);


   channelFactory.Close();


 


   return responseMessage;


}


Now, in order to handle the message conversion you would supplement the above code so that it identifies the message version received. Note that we are solely checking for netTcpBinding here, but this code could be modified to expand upon this to make it more generic.


public Message ProcessMessage(Message message)


{


   // Get the message version


   MessageVersion returnMessageVersion = message.Version;


   bool messageConverted = false;


 


   var channelFactory = new ChannelFactory<IMyIntermediaryService>(“destination”);


 


   IMyIntermediaryService forwardingChannel = channelFactory.CreateChannel(); 


 


   // If we are using NetTcpBinding make sure that the message we are sending is


   // Soap 1.2 WS-Addressing if it is not already


   if (channelFactory.Endpoint.Binding.GetType() == typeof(NetTcpBinding)


       && message.Version != MessageVersion.Soap12WSAddressing10)


   {


      message = CreateMessageCopy(message, MessageVersion.Soap12WSAddressing10);


      messageConverted = true;


   }


 


   Message responseMessage = forwardingChannel.ProcessMessage(message);


   channelFactory.Close();


 


   // Convert the message type back to that of the original if necessary


   if (messageConverted)


   {


      responseMessage = CreateMessageCopy(responseMessage, returnMessageVersion);


   }


   return responseMessage;


}


Note that you must also covert the result back to the original format if a conversion has taken place otherwise the client will throw an exception “An error occurred while receiving the HTTP response to http://myserver/myservice.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.”


The conversion method would be something like the following


private static Message CreateMessageCopy(


   Message message,


   MessageVersion newMessageVersion)


{


   Message copy = Message.CreateMessage(


      newMessageVersion,


      message.Headers.Action,


      message.GetReaderAtBodyContents());


   copy.Properties.CopyProperties(message.Properties);


   return copy;


}