Sie sind auf Seite 1von 28

WCF Bindings In Depth

Aaron Skonnard
Code download available at: ServiceStation2007_07.exe (162 KB)
Browse the Code Online

Contents What is a Binding? Built-In Bindings Configuring Bindings Defining a Custom Binding Making Custom Bindings Easy to Use Sharing Binding Descriptions Conclusion
The Windows Communication Foundation programming model makes it easy for developers to configure services with a variety of wire formats and message protocols. The binding is the secret sauce behind this simplicity. This month I show you in detail how the built-in bindings work, how to configure them, and how to define custom bindings of your own.

What is a Binding?
Ultimately, Windows Communication Foundation is a framework for building services that process XML messages. Windows Communication Foundation allows you to transmit messages using different transport protocols (such as HTTP, TCP, and MSMQ) and using different XML representations (such as text, binary, or MTOM, which is commonly referred to as the message encoding in Windows Communication Foundation). In addition, you can enhance specific messaging interactions with a suite of SOAP protocols, such as the various WS-* specifications around security, reliable messaging, and transactions. All three of these communication conceptsthe transport, the message encoding, and the suite of protocolsare central to what happens on the wire at run time. In Windows Communication Foundation, all of these communication details are handled by the channel stack (see Figure 1). Just as its name implies, the channel stack is a stack of channel components that all messages pass through during runtime processing. The bottom-most component is the transport channel. This implements the given transport protocol and reads incoming messages off the wire. The transport channel uses a message encoder to read the incoming bytes into a logical Message object for further processing.

Figure 1 Bindings and Channel Stacks (Click the image for a larger view)
After that, the message bubbles up through the rest of the channel stack, giving each protocol channel an opportunity to do its processing, until it eventually reaches the top and Windows Communication Foundation dispatches the final message to your service implementation. Messages undergo significant transformation along the way. Although the Windows Communication Foundation channel architecture provides a consistent and flexible messaging foundation, it would be too tedious for most developers to work with it directly. When building a channel stack, you have to think carefully about the ordering of the components and whether or not they are compatible with one another. So instead, Windows Communication Foundation provides a simpler abstractionthe concept of endpointsfor indirectly configuring the underlying channel stack. The idea is that you configure services with one or more endpoints in order to accommodate different communication scenarios. For each endpoint, you specify an address, a binding, and a contract. The address simply specifies the network address where you want to listen for messages while the contract specifies what the messages arriving at the specified address should contain. Its the binding, however, that provides the recipe for building the channel stack needed to properly process the messages. When you load a service, Windows Communication Foundation follows the instructions outlined by the binding description to create each channel stack. The binding binds your service implementation to the wire through the channel stack in the middle (Figure 1 illustrates this). This communication model allows you to think about the messaging features you need, in simple terms, while also allowing you to ignore the complexities of actually making it happen in the Windows Communication Foundation runtime environment. For more background on message processing fundamentals, see my April 2007 column on WCF Messaging Fundamentals.

Built-In Bindings
Within the Windows Communication Foundation programming model, bindings are represented by the System.ServiceModel.Channels.Binding class. All binding classes must derive from this base class. Figure 2 summarizes the built-in binding classes that come with Windows Communication Foundation out of the box.

Each class derives from Binding and defines a different channel stack configuration through its implementation. These built-in bindings address the most common messaging scenarios that youll run into today. Transaction flow is always disabled by defaultthe table shows the protocols that are used by default when you choose to enable transaction flow. Also note that MsmqIntegrationBinding doesnt use a Windows Communication Foundation message encodinginstead it lets you choose a pre-Windows Communication Foundation serialization format. Figure 2 Windows Communication Foundation Built-In Bindings Transaction Flow (disabled by default) Not Supported

Binding Class Name

Transport

Message Encoding Text

Message Version SOAP 1.1

Security Mode None

Reliable Messaging Not Supported

BasicHttpBinding

HTTP

WSHttpBinding

HTTP

Text

SOAP 1.2 WSAddressing 1.0

Message Disabled

WSAtomicTransactions

WSDualHttpBinding

HTTP

Text

SOAP 1.2 WSAddressing 1.0

Message Enabled

WSAtomicTransactions

WSFederationHttpBinding HTTP

Text

SOAP 1.2 WSAddressing 1.0

Message Disabled

WSAtomicTransactions

NetTcpBinding NetPeerTcpBinding

TCP P2P

Binary Binary

SOAP 1.2 SOAP 1.2

Transport Disabled Transport Not Supported

OleTransactions Not Supported

NetNamedPipesBinding

Named Pipes

Binary

SOAP 1.2

Transport Not Supported

OleTransactions

NetMsmqBinding

MSMQ

Binary

SOAP 1.2

Message Not Supported

Not Supported

MsmqIntegrationBinding MSMQ

Not Supported (uses a preWCF serialization

Not Supported

Transport Not Supported

Not Supported

format) CustomBinding You Decide You Decide You Decide You Decide You Decide You Decide

For example, the BasicHttpBinding was designed for scenarios where interoperability is of utmost importance. As a result, BasicHttpBinding uses HTTP for the transport and text for the message encoding. An important aspect of the message encoding is the expected message version, which happens to be SOAP 1.1 for BasicHttpBinding. As for additional protocols, BasicHttpBinding is capable of using transport or message security, but both are disabled by default. The other WS-* protocols are not supported with this binding. As a result, this binding produces a simple channel stack capable of interoperating with any other basic Web services implementationand this is a great choice when your number-one priority is to make things work. Then theres WSHttpBinding. This was also designed for interoperability while incorporating the richer Web services protocols for security, reliable messaging, and transactions. As a result, WSHttpBinding also uses HTTP for the transport and text for the message encoding, but it uses SOAP 1.2 along with WS-Addressing 1.0 for the message versionthey are needed to carry the additional Web services protocol headers. The binding enables message-based security (via WS-Security and friends) and is capable of supporting WS-ReliableMessaging and WS-AtomicTransactions if you choose to enable them. WSHttpBinding produces a more sophisticated channel stack and will most likely be constrained to enterprise scenarios where integration across frameworks and platforms is required. And that brings me to NetTcpBinding. Unlike the two HTTP bindings, the various "Net" bindings were not designed for interoperability. In fact, each was designed for optimizing a different communication scenario when you can safely assume you have the Microsoft .NET Framework 3.0 installed on both sides (this explains why the binding names are prefixed with "Net"). NetTcpBinding uses TCP for the transport, binary for the message encoding, and SOAP 1.2 for the message version. It enables transport security by default and can support transactions if enabled. As you can see, the configuration of this binding focuses on creating a channel stack that will perform better in Windows environments, giving you a great option for replacing your various COM+ and .NET remoting investments. All you have to do is choose a particular binding based on your communication needs (see Figure 2) and Windows Communication Foundation takes care of producing the appropriate channel stack. Programmatically you choose a binding by providing an instance of the desired binding class in your call to ServiceHost.AddServiceHost: Copy Code

using (ServiceHost host = new ServiceHost(typeof(ChatService))) { host.AddServiceEndpoint(typeof(IChat), new BasicHttpBinding(), http://localhost:8080/chat); host.AddServiceEndpoint(typeof(IChat), new WSHttpBinding(), http://localhost:8080/chat/secure); host.AddServiceEndpoint(typeof(IChat), new NetTcpBinding(), net.tcp://localhost:8081/chat);

host.Open(); ... // remaining code ommitted for brevity }


Or you can specify the binding name when defining endpoints in the hosts configuration file. When you specify an endpoint via configuration, the binding name must be written in camel case (for instance basicHttpBinding, wsHttpBinding, or netTcpBinding). Figure 3 illustrates how to configure the same three endpoints in the hosts configuration file. Figure 3 Configuring Endpoints in Hosts Configuration File Copy Code

<configuration> <system.serviceModel> <services> <service name=ChatService> <endpoint address=http://localhost:8080/chat binding=basicHttpBinding contract=IChat/> <endpoint address=http://localhost:8080/chat/secure binding=wsHttpBinding contract=IChat/> <endpoint address=net.tcp://localhost:8081/chat binding=netTcpBinding contract=IChat/> </service> </services> </system.serviceModel> </configuration>
The remaining bindings in Figure 2 target other common communication scenarios. For example, when you need bidirectional communication over HTTP, you can use WSDualHttpBinding, or when you want to implement asynchronous durable messaging, you can use NetMsmqBinding. When you need peer-to-peer capabilities for rich client applications, you can turn to NetPeerTcpBinding. Youll be hard-pressed to come up with communication scenarios that arent already addressed by one of these built-in bindings. However, its very likely that youll need to configure one of the built-in bindings in order to accommodate a specific integration issue.

Configuring Bindings

You can configure any of the built-in bindings by taking advantage of the various constructors and properties found on the classes. Once youve instantiated a binding object, you can modify its public writable properties before you pass the object to ServiceHost.AddServiceEndpoint. The following example illustrates how to configure a BasicHttpBinding object to use MTOM and transport security (HTTPS): Copy Code

BasicHttpBinding basicHttpBinding = new BasicHttpBinding(); basicHttpBinding.MessageEncoding = WSMessageEncoding.Mtom; basicHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport; host.AddServiceEndpoint( typeof(IChatService), basicHttpBinding, http://localhost:8080/chat); ...
You can accomplish the same thing entirely within configuration using the <bindings> configuration section. This mechanism allows you to define numerous named binding configurations for any of the built-in binding classes. Then you can apply a particular binding configuration to an endpoint through the <endpoint>s bindingConfiguration attribute. Figure 4 illustrates how to create a binding configuration named basicConfig thats also set up to use MTOM and transport security. Figure 4 Creating a Binding Configuration Copy Code

<configuration> <system.serviceModel> <services> <service name=ChatService> <endpoint address=http://localhost:8080/chat binding=basicHttpBinding bindingConfiguration=basicConfig contract=ChatLibrary.IChat /> ... </service> </services> <bindings> <basicHttpBinding> <binding name=basicConfig messageEncoding=Mtom> <security mode=Transport/> </binding> </basicHttpBinding> ... </bindings> </system.serviceModel>

</configuration>
Notice how the <endpoint> definition refers to basicHttpBinding for the binding name and basicConfig for the binding configuration. You can define multiple binding configurations for each known binding class when multiple endpoints need to use different binding configurations. Take a look at Figure 5 for an example. In this configuration file, Ive created two binding configurations for BasicHttpBindingboth enable transport security but one uses text while the other uses MTOM. The first endpoint is configured to use basicConfig1, the second basicConfig2. Both endpoints use the same binding class but two different configurations. Figure 5 Binding Configuration Examples Copy Code

<configuration> <system.serviceModel> <services> <service name=ChatService> <endpoint address=text binding=basicHttpBinding bindingConfiguration=basicConfig1 contract=IChat /> <endpoint address=mtom binding=basicHttpBinding bindingConfiguration=basicConfig2 contract=IChat /> <endpoint address=secure binding=wsHttpBinding bindingConfiguration=wsConfig contract=IChat /> <endpoint address= binding=netTcpBinding bindingConfiguration=tcpConfig contract=IChat /> </service> </services> <bindings> <basicHttpBinding> <binding name=basicConfig1 messageEncoding=Text> <security mode=Transport/> </binding> <binding name=basicConfig2 messageEncoding=Mtom> <security mode=Transport/> </binding> </basicHttpBinding> <wsHttpBinding> <binding name=wsConfig transactionFlow=true>

<security mode=TransportWithMessageCredential> <message clientCredentialType=UserName/> </security> <reliableSession enabled=true ordered=true/> </binding> </wsHttpBinding> <netTcpBinding> <binding name=tcpConfig transactionFlow=true transactionProtocol=WSAtomicTransactionOctober2004> <security mode=None/> <reliableSession enabled=true /> </binding> </netTcpBinding> </bindings> </system.serviceModel> </configuration>
Figure 5 also contains a configuration for WSHttpBinding, named wsConfig, which does several things. It enables transaction flow and ordered reliable messaging. It also changes the security mode to TransportWithMessageCredential and specifies a client credential type of UserNamethis means the channel stack will be configured to use transport security (HTTPS) but incoming messages will be expected to contain WS-Security <UsernameToken> elements. The final binding configuration shown in Figure 5 changes the defaults for NetTcpBinding. In this example, the binding configuration named tcpConfig enables transaction flow and changes the transaction protocol from OleTransactions (the default) to the October 2004 version of WS-AtomicTransaction. It also disables transport security, which is on by default, and enables WS-ReliableMessaging. The Windows Communication Foundation binding configuration mechanism can accommodate most of the integration scenarios. However, if luck still finds you stuck dealing with an obscure scenario that you cannot resolve, you can always define a custom binding to meet your exact needs.

Defining a Custom Binding


You define a custom binding by deriving a class from System.ServiceModel.Channels.Binding. Your implementation has one primary responsibility: to produce an ordered collection of BindingElement objects (an object of type BindingElementCollection). The runtime asks the binding instance to do this by calling its CreateBindingElements method at run time. At this point, the binding instance should look at its current configuration, create the various binding element objects it needs, and order them properly in the collection before returning it. The Windows Communication Foundation runtime walks through the binding element collection and uses it to create the underlying channel stack (this is essentially what I mean by the "recipe"). Theres a one-to-one mapping between the binding elements and the objects that end up in the channel stack at run time. Each of the built-in binding classes derives from Binding and provides a unique implementation of CreateBindingElements. You should whip out .NET Reflector (available at aisto.com/roeder/dotnet) and view the

implementation of each class. Youll learn exactly what binding elements each one uses and the order in which they are placed in the collection. This is valuable because youll be doing the exact same thing when you create a custom binding. Before you can create a custom binding, however, you must become familiar with the binding element classes that are available to you. A binding element is a class that derives from System.ServiceModel.Channels.BindingElement. Windows Communication Foundation ships with numerous BindingElement classes that are ready to use. Figures 6 through 9 describe most of the built-in BindingElement classes that are currently found in Windows Communication Foundation. Figure 6 lists the classes that represent the different transport protocols supported by Windows Communication Foundation. Figure 7 describes the classes that represent different types of transport security. Figure 8 describes the classes that represent the different message encodings. And finally, Figure 9 describes the classes that represent the layered protocols for security, reliable messaging, and transactions. Figure 9 Protocol Binding Elements Protocol Transaction Flow Reliable Messaging Security Class TransactionFlowBindingElement ReliableSessionBindingElement SecurityBindingElement Element <transactionFlow/> <reliableSession/> <security/>

Figure 8 Message Encoding Binding Elements Message Encoding Text MTOM Binary Class TextMessageEncodingBindingElement MtomMessageEncodingBindingElement BinaryMessageEncodingBindingElement Element <textMessageEncoding/> <mtomMessageEncoding/> <binaryMessageEncoding/>

Figure 7 Transport Security Binding Elements Transport Security Windows SSL Class WindowsStreamSecurityBindingElement SslStreamSecurityBindingElement Element <windowsStreamSecurity/> <sslStreamSecurity/>

Figure 6 Transport Binding Elements Transport HTTP HTTPS Class HttpTransportBindingElement HttpsTransportBindingElement Element <httpTransport/> <httpsTransport/>

TCP Named pipes MSMQ MSMQ P2P

TcpTransportBindingElement NamedPipeTransportBindingElement MsmqTransportBindingElement MsmqIntegrationBindingElement PeerTransportBindingElement

<tcpTransport/> <namedPipeTransport/> <msmqTransport/> <msmqIntegration/> <peerTransport/>

There is another BindingElement not listed in any of these figures. Its called CompositeDuplexBindingElement (<compositeDuplex/>) and its something of a special case because it doesnt fit into any of these groupings. You use it when you need to create a binding that supports duplex communications. You create a custom binding by instantiating CustomBinding and adding the desired BindingElement objects to its Elements collection. However, the order in which you add them is very important. Here are the order details:

You add to the collection from top to bottom. Only the transport binding element is officially required when defining a custom binding. Message encoding is required for each binding, but if you dont specify one, Windows Communication Foundation will add a default encoding for you. The default encoding for HTTP(S) is text and for all other transports it is binary. Heres an example of creating and using one of the simplest custom bindings possible: Copy Code

... CustomBinding myHttpBinding = new CustomBinding(); myHttpBinding.Name = myHttpBinding; myHttpBinding.Elements.Add(new HttpTransportBindingElement()); host.AddServiceEndpoint(typeof(IChat), myHttpBinding, http://localhost:8080/chat/custom); ...
The only BindingElement object I added was an instance of HttpTransportBindingElement. In this case, Windows Communication Foundation will choose to use the text message encoding when it builds the channel stack since its the default encoding for HTTP. This particular example produces a binding that ends up being identical to the built-in BasicHttpBinding.

However, you now have direct access to the underlying BindingElement objects, which gives you more flexibility and control over the resulting channel stack configuration. When you use one of the built-in binding classes, youre limited to the facade it provides over the underlying BindingElementCollection. Consider the example shown in Figure 10. It configures the individual BindingElement objects before adding them to the collection. The resulting binding uses a different message version than normal, SOAP 1.1 along with the August 2004 version of WS-Addressing, which may come in handy when you need to integrate with older Web services frameworks. It also uses a customized HTTP transport instance. Figure 10 Configuring the Individual BindingElement Objects Copy Code

... // instantiate message encoding element and configure TextMessageEncodingBindingElement text = new TextMessageEncodingBindingElement(); text.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004; // instantiate transport element and configure HttpTransportBindingElement http = new HttpTransportBindingElement(); http.TransferMode = TransferMode.Streamed; http.UseDefaultWebProxy = true; CustomBinding myHttpBinding = new CustomBinding(); myHttpBinding.Name = myHttpBinding; myHttpBinding.Elements.Add(text); myHttpBinding.Elements.Add(http); host.AddServiceEndpoint(typeof(IChat), myHttpBinding, http://localhost:8080/chat/custom); ...
Of course, you can accomplish the same thing entirely within configuration by creating a configuration for <customBinding> as illustrated in Figure 11. This technique works like configuring any other built-in binding. You define a configuration for customBinding and then apply it to an endpoint. The difference is that in this case youre defining the entire binding definition within the configuration. You dont get anything for free when using CustomBinding. Figure 11 Creating a Configuration for Copy Code

<configuration> <system.serviceModel> <services> <service name=ChatService> <endpoint

address=custom binding=customBinding bindingConfiguration=myBasicHttpBindingConfiguration contract=IChat /> </service> </services> <bindings> <customBinding> <binding name=myHttpBindingConfiguration> <textMessageEncoding messageVersion=Soap11WSAddressingAugust2004/> <httpTransport useDefaultWebProxy=true transferMode=Streamed/> </binding> </customBinding> </bindings> </system.serviceModel> </configuration>
Figure 12 shows a few more custom binding examples that use some of the other BindingElement classes shown in the figures. The myWSHttpBindingConfiguration configuration is similar to the built-in WSHttpBinding except it uses the binary message encoding and it enables transaction flow and ordered reliable messaging. The myNetTcpBindingConfiguration configuration is like NetTcpBinding except it uses the text message encoding and enables transaction flow. Figure 12 Custom Binding Configuration Examples Copy Code

<configuration> <system.serviceModel> ... <bindings> <customBinding> <binding name=myBasicHttpBindingConfiguration> <textMessageEncoding messageVersion=Soap11WSAddressingAugust2004/> <httpTransport allowCookies=true useDefaultWebProxy=true transferMode=Streamed/> </binding> <binding name=myWSHttpBindingConfiguration> <transactionFlow/> <reliableSession ordered=true/> <security authenticationMode=SspiNegotiated/> <binaryMessageEncoding/> <httpTransport/>

</binding> <binding name=myNetTcpBindingConfiguration> <transactionFlow/> <textMessageEncoding/> <windowsStreamSecurity/> <tcpTransport/> </binding> </customBinding> </bindings> </configuration>

Making Custom Bindings Easy to Use


Although CustomBinding is convenient for one-off customizations, you should define a custom Binding class when you need to make it easier to reuse. When you derive from Binding, you need to override its two abstract members: CreateBindingElements and Scheme. Your implementation of CreateBindingElements is where you create and return the collection of BindingElement objects. Suppose you want to create a custom HTTP binding that always uses the binary message encodingcall it NetHttpBindingand assume that you want to let the users of this binding configure two properties on the underlying HttpTransportBindingElement instanceTransferMode and UseDefaultWebProxy. The code in Figure 13 demonstrates how you can accomplish this. Figure 13 Custom HTTP Binding Copy Code

public class NetHttpBinding : Binding { private BinaryMessageEncodingBindingElement binary = new BinaryMessageEncodingBindingElement(); private HttpTransportBindingElement http = new HttpTransportBindingElement(); public override BindingElementCollection CreateBindingElements() { return new BindingElementCollection( new BindingElement[] { binary, http }); } public TransferMode TransferMode { get { return http.TransferMode; } set { http.TransferMode = value; } } public bool UseDefaultWebProxy

{ get { return http.UseDefaultWebProxy; } set { http.UseDefaultWebProxy = value; } } public override string Scheme { get { return http; } } }
With the code in place, developers can simply instantiate your NetHttpBinding class and apply the instance to an endpoint as illustrated here: Copy Code

... NetHttpBinding netHttp = new NetHttpBinding(); netHttp.TransferMode = TransferMode.Streamed; netHttp.UseDefaultWebProxy = true; host.AddServiceEndpoint(typeof(IChat), netHttp, http://localhost:8080/chat/nethttp); ...
This is much easier than dealing with CustomBinding. But if you want to make it even easier, you may want to make it possible to configure the NetHttpBinding via the Windows Communication Foundation configuration section. In order to do this, you need to implement a few more configuration-related classes. Figure 14 provides a complete example of the classes youll need. Figure 14 Custom Configuration Classes for NetHttpBinding Copy Code

public class NetHttpBindingConfigurationElement : StandardBindingElement { public NetHttpBindingConfigurationElement(string configurationName) : base(configurationName) { } public NetHttpBindingConfigurationElement() : this(null) { } protected override Type BindingElementType { get { return typeof(NetHttpBinding); } } [ConfigurationProperty(transferMode, DefaultValue = TransferMode.Buffered)] public TransferMode TransferMode {

get { return ((TransferMode)(base[transferMode])); } set { base[transferMode] = value; } } [ConfigurationProperty(useDefaultWebProxy, DefaultValue = false)] public bool UseDefaultWebProxy { get { return ((bool)(base[useDefaultWebProxy])); } set { base[useDefaultWebProxy] = value; } } protected override ConfigurationPropertyCollection Properties { get { ConfigurationPropertyCollection properties = base.Properties; properties.Add(new ConfigurationProperty(transferMode, typeof(TransferMode), TransferMode.Buffered)); properties.Add(new ConfigurationProperty(useDefaultWebProxy, typeof(bool), true)); return properties; } } protected override void InitializeFrom(Binding binding) { base.InitializeFrom(binding); NetHttpBinding netHttpBinding = ((NetHttpBinding)(binding)); this.TransferMode = netHttpBinding.TransferMode; this.UseDefaultWebProxy = netHttpBinding.UseDefaultWebProxy; } protected override void OnApplyConfiguration(Binding binding) { if (binding == null) { throw new System.ArgumentNullException(binding); } if (binding.GetType() != typeof(NetHttpBinding)) { throw new System.ArgumentException( Invalid binding type expected NetHttpBinding); } NetHttpBinding netHttpBinding = ((NetHttpBinding)(binding)); netHttpBinding.TransferMode = this.TransferMode;

netHttpBinding.UseDefaultWebProxy = this.UseDefaultWebProxy; } } public class NetHttpBindingSection : StandardBindingCollectionElement<NetHttpBinding, NetHttpBindingConfigurationElement> { }


With these classes in place, you can add a binding extension mapping to the configuration file so Windows Communication Foundation knows that netHttpBinding goes with the configuration classes shown in Figure 14. Now you can simply specify netHttpBinding for the binding name, and configure it within the <bindings> section like any other binding, as shown in Figure 15. (The MSDN documentation available at msdn2.microsoft.com/aa967561.aspx provides more complete custom binding examples.) Figure 15 Configuring netHttpBinding Copy Code

<configuration> <system.serviceModel> <services> <service name=ChatService> <endpoint address=nethttp binding=netHttpBinding bindingConfiguration=myNetHttpBindingConfiguration contract=ChatLibrary.IChat /> </service> </services> <bindings> <netHttpBinding> <binding name=myNetHttpBindingConfiguration transferMode=Streamed useDefaultWebProxy=true/> </netHttpBinding> </bindings> <extensions> <bindingExtensions> <add name=netHttpBinding type=NetHttpBindingSection, NetHttpBindingLibrary /> </bindingExtensions> </extensions> </system.serviceModel>

</configuration>
Ive covered all the major options and components related to implementing a custom binding. The only thing I havent yet discussed is how to write a custom BindingElement class, which may be necessary if you cant find one that fits your exact needs. For example, say you need to implement a custom transport. In such a case, youll need to implement the transport channel (which is non-trivial) and a corresponding BindingElement class in order to make it easy to use within a binding. Implementing custom channel components and binding elements are advanced extensibility topics that Ill save for a future column.

Sharing Binding Descriptions


Bindings are all about what happens on the wire. When you choose a particular binding, configure one in a special way, or define a custom binding, its vital for consumers to be able to discover the exact binding configuration so they can properly integrate with the endpoint. Services can share their binding configurations with consumers by exposing metadata in the form of Web Services Description Language (WSDL) and WSPolicy. You can enable metadata on a Windows Communication Foundation service through the <serviceMetadata> behavior. This allows developers to browse to the service description using a Web browser. You can also make the metadata available programmatically by enabling MEX (IMetadataExchange) on a separate endpoint. Once you have metadata enabled, Windows Communication Foundation automatically produces the appropriate WSDL definition for the service upon request. The binding configuration for each endpoint is translated into WS-Policy statements and embedded within the WSDL definition to specify the exact configuration. If you browse to a Windows Communication Foundation-generated WSDL definition, youll find these policy statements toward the top of the file. As long as the client is capable of doing everything found in the WS-Policy statement, it should be able to produce the necessary client-side configuration. When using Windows Communication Foundation on the client side, svcutil.exe inspects the policy statements found in the WSDL definition and translates them into a corresponding binding configuration section in the client configuration file (see Figure 16). The net result is that the client ends up with an equivalent channel stack for dispatching outgoing messages.

Figure 16 Sharing Binding Congfigurations via Metadata (Click the image for a larger view)

The following code illustrates how a Windows Communication Foundation client can automatically access all of the endpoints exposed by a service via MEX at run time: Copy Code

... ServiceEndpointCollection endpoints = MetadataResolver.Resolve(typeof(IChat), new EndpointAddress(http://localhost:8080/chat/mex)); foreach (ServiceEndpoint se in endpoints) { ChannelFactory<IChat> cf = new ChannelFactory<IChat>( se.Binding, se.Address); IChat client = cf.CreateChannel(); client.SendMessage(msg); } ...
With this code available on the client, you can add new endpoints to the service, each with a unique binding configuration. Each time you run the client it will invoke all of the endpoints using the correct configuration. This shows that the client is able to automatically discover each endpoints binding configuration. One thing that can potentially break interoperability, even when using Windows Communication Foundation on both sides, is when the service employs a custom BindingElement that the client doesnt have access to (such as a custom transport). Obviously, using any type of custom channel component requires agreement between the client and service, and both sides will require an appropriate implementation. This brings me to my final word of caution. Its easy to configure yourself out of interoperability by getting too fancy with a binding configuration for no good reason. Make sure you know what youre enabling and why. If you dont have a good reason for something, stay with the defaults. That said, when you do run into situations where interoperability fails when using the defaults, your first goal should be to figure out whats getting in the way and then you can configure the binding (or create a custom binding) that works around the problem at hand.

Conclusion
The Windows Communication Foundation binding architecture provides an elegant model for configuring what happens on the wire. You simply specify a binding and Windows Communication Foundation uses that as the recipe for building the channel stack at run time. Windows Communication Foundation ships with numerous built-in bindings that come preconfigured to address todays most common communication needs. However, when the built-in bindings dont fit the bill, you can configure them or create custom bindings of your own, making it possible to accommodate any tough integration scenario you encounter. Send your questions and comments for Aaron to sstation@microsoft.com.

Bindings Contents

WCF Built-in Bindings Binding Behaviors and Endpoints Bindings Summary Internet Binding Scenarios Intranet Binding Scenarios Binding Elements

Objectives

Understand what bindings and behaviors are and how they are used in WCF. Understand when to use each binding supplied by WCF. Understand which bindings are best for the Internet. Understand which bindings are best for an intranet.

Overview
Microsoft Windows Communication Foundation (WCF) is a framework for building services that allows you to transmit messages using different transport protocols and different XML representations. It allows you to enhance message interactions with a suite of Simple Object Access Protocol (SOAP) protocols. WCF uses a channel stack that handles all of these communication details. It would be challenging to build a channel stack from scratch, as you would have to decide the ordering of the components and whether or not they are compatible with one another. For this reason, WCF indirectly configures the underlying channel stack with the help of configurable endpoints. An endpoint specifies an address, a binding, and a contract. The address specifies the network address where you want to listen for messages; the contract specifies what the messages arriving at the specified address should contain; and the binding provides the channel stack needed to process the message. When loading a service, WCF builds the channel stack by following the instructions outlined by the binding description.

WCF Built-in Bindings


Bindings define how clients can connect and communicate with your service. All the bindings in WCF are represented by the System.ServiceModel.Channels.Binding class, which is the base class for all bindings. Each class defines a different channel stack configuration through its implementation. A binding includes definition for the WS-* protocols used, the message encoding, and the transport protocol. WCF comes out of the box with a set of bindings configured for the most-common scenarios. If none of the bindings are a good fit, you can create a custom binding to configure the service explicitly to meet your needs. The following table summarizes common bindings.

Binding
basicHttpBinding

Description
Represents a binding that configures and exposes endpoints that are able to communicate with ASMX-based Web services and clients and other services that conform to the WS-I Basic Profile 1.1 specification. By default, basicHttpBinding has security disabled.

wsHttpBinding

Defines a secure, reliable, interoperable binding suitable for non-duplex service contracts. The binding implements the following specifications: WSReliable Messaging for reliability, and WS-Security for message security and authentication. The transport is HTTP, and message encoding is text/XML encoding. By default, it provides message security using Windows authentication.

ws2007HttpBinding

Defines a secure, reliable, interoperable binding suitable for non-duplex service contracts. The binding implements the following specifications: WSReliable Messaging for reliability, and WS-Security for message security and authentication. The transport is HTTP, and message encoding is text/XML encoding. The ws2007HttpBinding provides binding similar to wsHttpBinding but uses the standard for OASIS (Organization for the Advancement of Structured Information Standards). By default, it provides message security using Windows authentication.

netTcpBinding

Specifies a secure, reliable, optimized binding suitable for cross-machine communication. By default, it generates a run-time communication stack with transport security and Windows authentication as default security settings. It uses the Transmission Control Protocol (TCP) for message delivery, and binary message encoding.

netNamedPipeBinding

Defines a binding that is secure, reliable, and optimized for cross-process communication on the same machine. By default, it generates a run-time communication stack with WS-ReliableMessaging for reliability, transport security for transfer security, named pipes for message delivery, and binary message encoding. It is not secured by default.

netMsmqBinding

Defines a queued binding suitable for cross-machine communication.

wsFederationHttpBinding

Defines a binding that supports federated security. It helps in implementing federation, which is the ability to flow and share identities across multiple enterprises or trust domains for authentication and authorization. WCF implements federation over message and mixed mode security but not over transport security. Services configured with this binding must use the HTTP protocol as transport.

ws2007FederationHttpBinding Defines a binding that derives from wsFederationHttpBinding and supports federated security. It helps in implementing federation. WCF implements federation over message and mixed mode security but not over transport security. Services configured with this binding must use the HTTP protocol as transport. The ws2007FederationHttpBinding provides binding similar to ws2007FederationHttpBinding but uses the OASIS standard.

wsDualHttpBinding

Defines a secure, reliable, and interoperable binding that is suitable for duplex service contracts or communication through SOAP intermediaries.

customBinding

Allows you to create a custom binding with full control over the message stack.

For more information on bindings, see Windows Communication Foundation Bindings.

Binding Behaviors and Endpoints


A WCF service endpoint comprises an address, a binding, and a contract. Bindings define how clients can connect and communicate with your service. A binding includes definitions for the WS-* protocols used, the message encoding, and the transport protocol. For instance, wsHttpBinding uses HTTP, XML 1.0 encoding, message security, reliable sessions, and transactions by default. Bindings are exposed by a service endpoint that includes the binding plus a uniform resource identifier (URI) to which the client will send messages. Bindings can be configured either through code or by using configuration elements in the configuration file. The following example shows wsHttpBinding configured to use transport security: Copy

<bindings> <wsHttpBinding> <binding name="wsHttpEndpointBinding"> <security mode="Transport"> </security> </binding> </wsHttpBinding> </bindings>

The following configuration snippet shows an endpoint that exposes this binding: Copy

<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBind ing" name="wsHttpEndpoint" contract="IService">

When creating an overall security policy for your services, you will use bindings and behaviors to configure your service as follows:

Bindings. Bindings control the security mode, client credential type, and other security settings. Behaviors. Behaviors control impersonation levels, how client credentials are authenticated and authorized, and service credentials.

Bindings Summary
Use the following binding summaries to help you choose the right binding for your scenario.

basicHttpBinding
If your service needs to support legacy clients that expect an ASMX Web service, consider using basicHttpBinding. Because basicHttpBinding does not implement any security by default, if you require message or transport security, you should configure it explicitly on this binding. Use basicHttpBinding to expose endpoints that are able to communicate with ASMX-based Web services and clients and other services that conform to the WS-I Basic Profile 1.1 specification. When configuring transport security, basicHttpBinding

defaults to no credentials just like a classic ASMX Web service. basicHttpBinding allows you to host your service in Internet Information Services (IIS) 5.0 or IIS 6.0.

wsHttpBinding
If your service will be called by WCF clients over the Internet, consider using wsHttpBinding. wsHttpBinding is a good choice for Internet scenarios in which you do not have to support legacy clients that expect an ASMX Web service. If you do need to support legacy clients, consider using basicHttpBinding instead. wsHttpBinding allows you to host your service in IIS 5.0 or IIS 6.0.

netTcpBinding
If you need to support clients within your intranet, consider using netTcpBinding. netTcpBinding is a good choice for an intranet scenario if transport performance is important to you and it is acceptable to host the service in a Windows service instead of in IIS. netTcpBinding uses the TCP protocol and provides full support for SOAP security, transactions, and reliability. Use this binding when you want to provide a secure and reliable binding environment for .NET-to-.NET cross-machine communication. netTcpBinding does not allow you to host your service in IIS 5.0 or IIS 6.0; instead, host in a Windows service or in IIS 7.0.

netNamedPipeBinding
If you need to support WCF clients on the same machine as your service, consider using netNamedPipeBinding. netNamedPipeBinding provides a secure and reliable binding environment for crossprocess, same-machine communication. Use this binding when you want to make use of the Named-Pipe protocol and provide full support for SOAP security, transactions, and reliability. netNamedPipeBinding does not allow you to host your service in IIS 5.0 or IIS 6.0; instead, host in a Windows service or in IIS 7.0.

netMsmqBinding
If you need to support disconnected queuing, use netMsmqBinding. Queuing is provided by using Microsoft Message Queuing (MSMQ) as a transport, which enables support for disconnected operations, failure isolation, and load leveling. You can use netMsmqBinding when the client and the service do not have to be online at the same time. You can also manage any number of incoming messages by using load leveling. MSMQ supports failure isolation, where messages can fail without affecting the processing of other messages. netMsmqBinding does not allow you to host your service in IIS 5.0 or IIS 6.0; instead, host in a Windows service or in IIS 7.0.

wsDualHttpBinding
If you need to support a duplex service, use wsDualHttpBinding. A duplex service is a service that uses duplex message patterns, which provides the ability for a service to communicate back to the client via a callback. You can also use this binding to support communication via SOAP intermediaries. wsDualHttpBinding does not allow you to host your service in IIS 5.0 or IIS 6.0; instead, host in a Windows service or in IIS 7.0.

CustomBinding

A custom binding is created in code by using the CustomBinding class found in the System.ServiceModel.Channels namespace. This class exposes a collection of binding elements to which you can add further binding elements. This allows you to compose a new binding based on a set of existing binding elements. User-defined bindings are bindings that are created by inheriting from the Binding class. Creating user-defined bindings is preferred when you want to reuse the binding in a number of applications.

Internet Binding Scenarios


If you are exposing your WCF service interface over the Internet, use the following guidelines to help choose the appropriate binding:

If you are exposing your WCF service over the Internet to clients that expect a legacy ASMX Web service, use basicHttpBinding. Keep in mind that this binding does not have any security enabled by default, so all messages will be sent in plaintext format. If you are exposing your WCF service over the Internet to Windows Forms clients, use wsHttpBinding. wsHttpBinding provides the best WS-* interoperability features, including WS-SecureConversation, WS-Addressing, and WS-AtomicTransaction. The combination of features offered by wsHttpBinding makes for the most reliable connection offered by WCF over the Internet. If you are exposing your WCF service over an intranet to an ASP.NET application, which in turn is exposed to the clients over the Internet, use netTcpBinding. If your clients and the service require full-duplex communication, then use wsDualHttpBinding. It is the only binding that supports full-duplex. If your service is interacting with Web Services Enhancements (WSE) clients, you must use customBinding. The service must use a custom binding to be compatible with the August 2004 version of the WS-Addressing specification.

Intranet Binding Scenarios


If you are exposing your WCF service interface over an intranet, use the following guidelines to help choose the appropriate binding:

If you are exposing your WCF service over your intranet to clients that expect a legacy ASMX Web service, use basicHttpBinding. Keep in mind that this binding does not have any security enabled by default, so all messages will be sent in plaintext format. If you are exposing your WCF service over your intranet to Windows Forms or ASP.NET clients, use netTcpBinding. You can use any binding over an intranet, but netTcpBinding provides the best throughput performance. On an intranet, you generally do not need to worry as much about the connection going down as with an Internet connection, so some of the WS-* advantages supplied with wsHttpBinding may not be as necessary on an intranet.

Binding Elements
WCF provides numerous channels and encoders that are used in the preconfigured bindings. You can use these channels to provide binding elements that can be used in custom bindings.

A binding element is a class that derives from System.ServiceModel.Channels.BindingElement. WCF provides some different lists of binding elements that include the Protocol Binding Elements, Message Encoding Binding Elements, Transport Security Binding Elements, and Transport Binding Elements.

Protocol Binding Elements Protocol


Transaction Flow

Class
TransactionFlowBindingElement

Element
<transactionFlow/>

Reliable Messaging

ReliableSessionBindingElement

<reliableSession/>

Security

SecurityBindingElement

<security/>

Message Encoding Binding Elements Message encoding


Text

Class
TextMessageEncodingBindingElement

Element
<textMessageEncoding/>

MTOM

MtomMessageEncodingBindingElement

<mtomMessageEncoding/>

Binary

BinaryMessageEncodingBindingElement

<binaryMessageEncoding/>

Transport Security Binding Elements Transport security


Windows

Class
WindowsStreamSecurityBindingElement

Element
<windowsStreamSecurity/>

SSL

SslStreamSecurityBindingElement

<sslStreamSecurity/>

Transport Binding Elements

Transport
HTTP

Class
HttpTransportBindingElement

Element
<httpTransport/>

HTTPS

HttpsTransportBindingElement

<httpsTransport/>

TCP

TcpTransportBindingElement

<tcpTransport/>

Named pipes

NamedPipeTransportBindingElement

<namedPipeTransport/>

MSMQ

MsmqTransportBindingElement

<msmqTransport/>

MSMQ

MsmqIntegrationBindingElement

<msmqIntegration/>

P2P

PeerTransportBindingElement

<peerTransport/>

You can add binding elements by adding the desired BindingElement objects to its Elements collection. The order in which the binding element is added is very important. The order of adding the binding elements is as follows: 1. 2. 3. 4. 5. 6. 7. Transaction Flow (not required) Reliable Messaging (not required) Message Security (not required) Composite Duplex (not required) Message Encoding (required) Transport Security (not required) Transport (required)

The Transport binding element is the only required element when defining a custom binding. The Message Encoding element is required for each binding, but if you do not specify one, WCF will add a default encoding. The default encoding for HTTP(S) is text, and for all other transports it is binary. The following code shows how to create a custom binding: Copy

CustomBinding myHttpBinding = new CustomBinding();

myHttpBinding.Name = myHttpBinding; myHttpBinding.Elements.Add(new HttpTransportBindingElement());

host.AddServiceEndpoint(typeof(IChat), myHttpBinding, http://localhost:8080/chat/custom);

The following code shows how to create a custom binding by using the customBinding element in the configuration: Copy

<bindings> <customBinding> <binding name=myHttpBindingConfiguration> <textMessageEncoding messageVersion=Soap11WSAddressingAugust2004/> <httpTransport useDefaultWebProxy=true transferMode=Streamed/> </binding> </customBinding> </bindings>

Custom Binding Configuration Examples


The following example shows a custom binding that performs functions similar to those of wsHttpBinding and netTcpBinding: Copy

<configuration> <system.serviceModel>

<bindings> <customBinding>

<binding name=myWSHttpBindingConfiguration> <transactionFlow/> <reliableSession ordered=true/> <security authenticationMode=SspiNegotiated/> <binaryMessageEncoding/> <httpTransport/> </binding> <binding name=myNetTcpBindingConfiguration> <transactionFlow/> <textMessageEncoding/> <windowsStreamSecurity/> <tcpTransport/> </binding>

</customBinding> </bindings> </system.serviceModel> </configuration>

The myWSHttpBindingConfiguration configuration is similar to the built-in wsHttpBinding except that it uses binary message encoding and enables transaction flow and ordered reliable messaging. The myNetTcpBindingConfiguration configuration is similar to netTcpBinding except that it uses text message encoding and enables transaction flow

Das könnte Ihnen auch gefallen