There is a common functionality request in modern distributed applications that clients and services (client also being other services) could communicate using different communication protocols and/or different transport semantics inside a single protocol.
For this sample we're going to limit ourselves to HTTP messaging, but this does not limit the scope of the article. Other transport protocols can be added without obstructing other transport mechanisms.
To allow this scenario Indigo (Windows Communication Foundation, WCF) allows multiple endpoints per service to be setup. Service side bindings can, for example, be the following:
<bindings> <wsProfileBinding> <binding configurationName="Secure" orderedSession="false" reliableSessionEnabled="false" securityMode="WSSecurityOverHttp" maxMessageSize="134217728" flowTransactions="NotAllowed" messageEncoding="Text"> <wsSecurity authenticationMode="Certificate" useNegotiation="true" /> </binding> <binding configurationName="SecureReliable" orderedSession="true" reliableSessionEnabled="true" securityMode="WSSecurityOverHttp" maxMessageSize="134217728" flowTransactions="NotAllowed" messageEncoding="Text"> <wsSecurity authenticationMode="Certificate" useNegotiation="true" /> </binding> <binding configurationName="SecureReliableTransacted" orderedSession="true" reliableSessionEnabled="true" securityMode="WSSecurityOverHttp" maxMessageSize="134217728" flowTransactions="Allowed" messageEncoding="Text"> <wsSecurity authenticationMode="Certificate" useNegotiation="true" /> </binding> <binding configurationName="SecureMTOM" orderedSession="false" reliableSessionEnabled="false" securityMode="WSSecurityOverHttp" maxMessageSize="134217728" flowTransactions="NotAllowed" messageEncoding="Mtom"> <wsSecurity authenticationMode="Certificate" useNegotiation="true" /> </binding> <binding configurationName="SecureReliableMTOM" orderedSession="true" reliableSessionEnabled="true" securityMode="WSSecurityOverHttp" maxMessageSize="134217728" flowTransactions="NotAllowed" messageEncoding="Mtom"> <wsSecurity authenticationMode="Certificate" useNegotiation="true" /> </binding> <binding configurationName="SecureReliableTransactedMTOM" orderedSession="true" reliableSessionEnabled="true" securityMode="WSSecurityOverHttp" maxMessageSize="134217728" flowTransactions="Allowed" messageEncoding="Mtom"> <wsSecurity authenticationMode="Certificate" useNegotiation="true" /> </binding> </wsProfileBinding></bindings>
There are six different bindings setup:
The Secure binding uses WS-Security/WS-SecureConversation pair to secure all outgoing and incoming messages using encryption and digital signing. We’re not going to drill down into it in this post. I’m going to write another one where different certificate mechanisms will be discussed.
The SecureReliable binding also uses WS-ReliableMessaging with message ordering and guaranteed delivery turned on.
The SecureReliableTransacted endpoint also uses WS-AtomicTransaction to implement transaction semantics between the client and the service.There are another three bindings (*MTOM) with the same transport semantics as well as MTOM encoding turned on. Since services can support transfer of large binary files, we have also set the maxMessageSize attribute in every binding to 128 MB.
Endpoint configuration for this service is:
<services> <service serviceType="Indigo.Demos.TransferService" behaviorConfiguration="DefaultBehavior"> <endpoint address="http://localhost:666/TransferService.svc/" bindingNamespace= "http://webservices.gama-system.com/bindings" bindingName="Default" bindingSectionName="wsProfileBinding" bindingConfiguration="SecureReliableMTOM" contractType="Indigo.Demos.ITransferContract"/> <endpoint address= "http://localhost:666/TransferService.svc/secure" bindingNamespace= "http://webservices.gama-system.com/bindings" bindingName="Secure" bindingSectionName="wsProfileBinding" bindingConfiguration="Secure" contractType="Indigo.Demos.ITransferContract"/> <endpoint address= "http://localhost:666/TransferService.svc/ securereliable" bindingNamespace= "http://webservices.gama-system.com/bindings" bindingName="SecureReliable" bindingSectionName="wsProfileBinding" bindingConfiguration="SecureReliable" contractType="Indigo.Demos.ITransferContract"/> <endpoint address= "http://localhost:666/TransferService.svc/ securereliabletransacted" bindingNamespace= "http://webservices.gama-system.com/bindings" bindingName="SecureReliableTransacted" bindingSectionName="wsProfileBinding" bindingConfiguration="SecureReliableTransacted" contractType="Indigo.Demos.ITransferContract"/> <endpoint address= "http://localhost:666/TransferService.svc/ secureMTOM" bindingNamespace= "http://webservices.gama-system.com/bindings" bindingName="SecureMTOM" bindingSectionName="wsProfileBinding" bindingConfiguration="SecureMTOM" contractType="Indigo.Demos.ITransferContract"/> <endpoint address= "http://localhost:666/TransferService.svc/ securereliableMTOM" bindingNamespace= "http://webservices.gama-system.com/bindings" bindingName="SecureReliableMTOM" bindingSectionName="wsProfileBinding" bindingConfiguration="SecureReliableMTOM" contractType="Indigo.Demos.ITransferContract"/> <endpoint address= "http://localhost:666/TransferService.svc/ securereliabletransactedMTOM" bindingNamespace= "http://webservices.gama-system.com/bindings" bindingName="SecureReliableTransactedMTOM" bindingSectionName="wsProfileBinding" bindingConfiguration="SecureReliableTransactedMTOM" contractType="Indigo.Demos.ITransferContract"/> </service></services>
It can be seen that almost every endpoint (two are bound to the same binding) is bound to a different binding.The service is therefore exposing its functionality using the following endpoints:
The first endpoint in this example is considered a default one and is mapped to the same binding as the *securereliableMTOM endpoint.
The problem with this is that current WCF’s WSDLExporter maps different endpoints into WSDL ports, but WSDL ports have a requirement to be uniquely named. The default port name construction is done by using the binding type name (i.e. wsProfileBinding, basicProfileBinding), which is concatenated with the contract name.
Therefore, when one has defined multiple bindings from the same binding type a name collision occurs (six WSDL ports with the same QName (namespace and local name)). This can be avoided using a bindingNamespace attribute as well as bindingName attribute. In this example we set the bindingNamespace to http://webservices.gama-system.com/bindings for all bindings and made the name unique by using the bindingName attribute.
There are currently two weird design decisions in multiple binding support of WCF. First bindingNamespace and bindingName attributes are bound to endpoints and not bindings. It would probably be more appropriate to put binding’s namespace and name into the <binding> element. Second, binding name is not propagated into WSDL properly when the same binding is used in two or more endpoints (in this example http://localhost:666/TransferService.svc/ and http://localhost:666/TransferService.svc/securereliableMTOM endpoints are bound to Default binding. If you look closely into the generated WSDL, you will see that the matching WSDL ports are not named after bindingName attribute.
These are non-breaking issues and will probably be addressed for beta 2 of WCF.
In the next Indigo series post, we’ll look closely into the security characteristics of certificate based authentication.
Remember Me
The opinions expressed herein are my own personal opinions and do not represent my company's view in any way.
My views often change.
This blog is just a collection of bytes.
Copyright © 2003-2024Matevž Gačnik
E-mail