Windows Communication Foundation (WCF) services are wire-level compatible with Web Services Enhancements 3.0 (WSE3) clients. This is correct in theory, however, it's not as easy as one would expect. This article presents the issues on interoperability between WCF and WSE 3.0.
Web Services Enhancements 3.0 released in 2005 (CTP about July 2005) provides a number of new enhancements for web services. That includes the ability to host web services outside IIS, the SOAP Message Transmission Optimisation Mechanism (MTOM), plus additional security features. According to many sources WSE 3.0 was a step in the WCF direction. The most important problem is the fact that WSE 3.0 do not interoperate with WSE 2.0 applications. The main reason for that are changes in some of WS-* specifications used by the new WSE version.
Windows Communication Foundation was released at end of 2006 as a part of .NET Framework 3.0. WCF unifies Web Services, .NET Remoting, Distributed Transactions and Message Queues into a single service-oriented programming model. WCF extends the declarative model, much more so than WSE 3.0. WS-* specifications used in WCF are the same as in WSE 3.0 which makes those two interoperable.
According to the above, WSE and WCF should be able to understand each other without any problems. In the next part I'm going to investigate WCF as a client to WSE 3.0 ASMX service.
WCF to WSE 3.0
In situation when WCF application acts as a client for WSE 3.0 service all work is done in few minutes. First thing is to generate proxy using svcutil.exe. A set of classes and interfaces will be generated for each protocol defined in asmx service web.config file. This includes client class and its interface, message classes and channel interface. If you were using "Add Service Reference" option from the Visual Studio "Orcas" you should have app.config file with binding and endpoint configuration generated as well. Those who prefer to use the svcutil.exe have to create such file on their own or create binding and endpoint directly in a client code. The following snippet presents sample client configuration.
1 <?xml version="1.0" encoding="utf-8" ?>
6 <binding name="Service1Soap12">
7 <textMessageEncoding messageVersion="Soap12WSAddressingAugust2004" />
8 <httpTransport />
13 <endpoint address="http://localhost/wse3/service.asmx" binding="customBinding"
14 bindingConfiguration="Service1Soap12" contract="Service.Service1Soap12"
15 name="Service1Soap12" />
To create this example an anonymous web service was used so all security elements are omitted to get better visibility of the addressing problem. The configuration is pretty straightforward however there is one small catch which I will explain in a moment. Generally speaking the configuration uses the custom binding to specify the message version and transport over HTTP. The endpoint configuration is absolutely typical. What is important in that configuration is the message version.
Theory says that WSE 3.0 and WCF are both using the same WS-* specifications. That is true however not by default. The most important detail from our point of view is the Web Service Addressing (WS-Addressing ) specification used on both side of the equation. WSE 3.0 supports the version from 10th August 2004 while WCF uses version 1.0 described in the W3C Recommendation from 9th May 2006. The differences in both versions mean that both ends didn't understand each other. One of the most visible differences is the Content-Type sent in the HTTP header. When a service is using WS-Addressing from the 10th August 2004 the header contains
Content-Type: application/soap+xml; charset=utf-8; action=http://tempuri.org/IService/Echo
while with version 1.0 of WS-Addressing the same header is
Content-Type: application/soap+xml; charset=utf-8.
This header difference causes an error because the WCF service is not expecting action in the Content-Type.
Fortunately WCF is able to use both versions of WS-Addressing. What we need to do is set up the proper message version in the binding configuration to tell the client which addressing specification should be used to communicate with the service. The default value for that property is Soap12Addressing10, which means that all messages are using WS-Addressing 1.0 and SOAP 1.2. To be compatible with WSE 3.0 services we have to change that value to Soap12AddressingAugust2004; which means that messages will be still compatible with SOAP 1.2 but use addressing from August 2004 will be used instead.
WSE 3.0 to WCF
When we know the issues about WS-addressing supported by WSE 3.0 and WCF configuring the WSE 3.0 client to work with the WCF service is pretty obvious. Assuming we already have some WCF clients for the service, we have to add a separated endpoint with a custom binding. The following snippet shows a sample configuration for the service.
1 <?xml version="1.0" encoding="utf-8" ?>
5 <service name="Host.Service" behaviorConfiguration="Host.ServiceBehavior">
8 <add baseAddress="http://localhost:8080/Service1" />
11 <endpoint address="" binding="wsHttpBinding" contract="Host.IService" bindingConfiguration="wsHttpBinding" />
12 <endpoint address="2004" binding="customBinding" contract="Host.IService" bindingConfiguration="AddressingAugust2004" />
13 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
18 <binding name="AddressingAugust2004">
19 <textMessageEncoding messageVersion="Soap12WSAddressingAugust2004">
21 <httpTransport />
25 <binding name="wsHttpBinding">
31 <behavior name="Host.ServiceBehavior">
32 <serviceMetadata httpGetEnabled="True"/>
Similarly the client configuration message version has been changed to deliver the proper addressing version. When we compare both configurations you will see that the bindings are exactly the same so we reflected the WSE 3.0 service configuration inside the WCF service.
The last thing I want to mention is an article I found on MSDN about interoperability between the WSE 3.0 and the WCF. This article pushed me towards the right solution, however, it contains one error: In the service configuration example the messageVersion is set to Soap11WSAddressingAugust2004 value which means Soap 1.1 and WS-Addressing from 10/08/2004 while WSE 3.0 is using SOAP in 1.2 version so the correct value is Soap12WSAddressingAugust2004.
I would like to thank my friend Paul for review of this article.
07-18-2007 9:48 AM