Address
, Binding
, and Contract
are commonly referred to as the "ABCs" of WCF. Address
is specifies the absolute or relative path or the URI (Uniform Resource Indicator) of the service. In WCF, Binding
is used to specify the transport channel that your service uses. Contract
specifies the contract that the service endpoint exposes to the outside world. In this section, I focus on the the supported types of Binding
in WCF 4.5.
The following are the types of transport channels supported:
- HTTP
- TCP
- Message Queuing
- Pipes
Table 1 lists the various binding classes in WCF, the transport and message modes, message encoding types, security modes, and transaction support.
Binding Class
|
Transport
|
Transport Mode
|
Message Mode
|
Message Encoding
|
Security Mode
|
Reliable Messaging
|
Transaction Flow
|
BasicHttpBinding |
HTTP
|
Yes
|
Yes
|
Text
|
None
|
Not Supported
|
Not Supported
|
WSHttpBinding |
HTTP
|
Yes
|
Yes
|
Text
|
Message
|
Disabled
|
WS-AtomicTransactions
|
WSDualHttpBinding |
HTTP
|
No
|
Yes
|
Text
|
Message
|
Enabled
|
WS-AtomicTransactions
|
WSFederationHttpBinding |
HTTP
|
No
|
Yes
|
Text
|
Message
|
Disabled
|
WS-AtomicTransactions
|
NetTcpBinding |
TCP
|
Yes
|
Yes
|
Binary
|
Transport
|
Disabled
|
OleTransactions
|
NetPeerTcpBinding |
P2P
|
Binary
|
Transport
|
Not Supported
|
Not Supported
| ||
NetNamedPipesBinding |
Named Pipes
|
Yes
|
No
|
Binary
|
Transport
|
Not Supported
|
OleTransactions
|
NetMsmqBinding |
MSMQ
|
Yes
|
Yes
|
Binary
|
Message
|
Not Supported
|
Not Supported
|
MsmqIntegrationBinding |
MSMQ
|
Yes
|
No
|
Not Supported
|
Transport
|
Not Supported
|
Not Supported
|
Table 1: Binding classes in WCF.
Let's now have a quick look at all the supported binding types in WCF.
BasicHttpBinding
BasicHttpBinding
is the simplest type of binding used. It provides support for both HTTP and HTTPS protocol. The following code snippet illustrates how this type of binding can be specified.
1
2
3
4
5
6
7
8
9
| < bindings > < basicHttpBinding > < binding name = "DDJServiceBinding" > < security mode = "Transport" > < transport clientCredentialType = "None" /> </ security > </ binding > </ basicHttpBinding > </ bindings > |
WsHttpBinding
WsHttpBinding
is an enhanced form of binding that encrypts the SOAP message. It provides support for both HTTP and HTTPS protocols, and both Text and MTOM encoding methods.
1
2
3
4
5
6
| < binding name = " DDJServiceBinding " > < security mode = "TransportWithMessageCredential" > < transport clientCredentialType = "None" /> < message clientCredentialType = "IssuedToken" /> </ security > </ binding > |
NetTcpBinding
NetTcpBinding
is based on the TCP protocol and is a type of binding that provides support for both transactions and security. It uses transport security by default.
1
2
3
4
5
6
7
8
| < client > binding = "netTcpBinding" contract = "IDDJService" > < identity > < servicePrincipalName value=”DDJService/Joydip-PC” /> </ identity > </ endpoint > </ client > |
NetNamedPipeBinding
In WCF,
NetNamedPipeBinding
is used for cross-process communication. This type of binding uses transport security and supports message encryption and signing. Here's an example that shows how you can specify this type of binding for your service:
1
2
3
4
5
6
7
8
9
10
| < services > < service name = "DDJService" behaviorConfiguration = "DDJService Behavior" > < host > < baseAddresses > </ baseAddresses > </ host > < endpoint address = "" binding = "netNamedPipeBinding" contract = "IDDJService " ></ endpoint > </ service > </ services > |
And here is how the
netNamedPipeBinding
client configuration would look:
1
2
3
4
5
| < client > < endpoint binding = "netNamedPipeBinding" contract = "IDDJService " ></ endpoint > </ client > |
MsmqIntegrationBinding
MsmqIntegrationBinding
is used in situations where you would like to have your service and client interoperate with non-WCF MSMQ clients.NetMsmqBinding
The
NetMsmqBinding
type of binding is used in a cross-machine environment. It employs MSMQ as the transport channel.NetPeerTcpBinding
NetPeerTcpBinding
is used for peer-to-peer network applications where services and service clients can intercommunicate. The following code snippet illustrates how you can configure this type of binding:
1
2
3
4
5
6
7
8
9
10
11
12
13
| < endpoint binding = "netPeerTcpBinding" bindingConfiguration = "netp2pBinding" contract = "IDDJService" > < bindings > < netPeerTcpBinding > < binding name = "netP2P" > < resolver mode = "Pnrp" /> < security mode = "None" /> </ binding > </ netPeerTcpBinding > </ bindings > |
WsDualHttpBinding
If you need support for Duplex Message Exchange (where services can communicate with their clients through callbacks), you need to use
WsDualHttpBinding
. In essence, it isWsHttpBinding
with support for a Duplex Message Exchange pattern.WsFederationHttpBinding
In WCF,
WsFederationHttpBinding
is used for federated security.Custom Binding
You can implement your own custom binding class for additional transport protocols, security, etc. To implement a custom binding class, you need to derive a class from
System.ServiceModel.Channels.Binding class
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| using System.ServiceModel.Channels; namespace DDJService { public class DDJSecureBinding : System.ServiceModel.Channels.Binding { private HttpTransportBindingElement transport = new HttpTransportBindingElement(); private BinaryMessageEncodingBindingElement encoding = new BinaryMessageEncodingBindingElement(); public override BindingElementCollection CreateBindingElements() { BindingElementCollection bindingElements = new BindingElementCollection(); bindingElements.Add( this .encoding); bindingElements.Add( this .transport); return bindingElements; } public override string Scheme { get { return this .transport.Scheme; } } } } |
The following code illustrates how you can configure your custom binding class programmatically.
1
2
3
4
5
6
| DDJSecureBinding bindingObject = new DDJSecureBinding(); bindingObject.Elements.Add( new BinaryMessageEncodingBindingElement()); bindingObject.Elements.Add( new HttpTransportBindingElement()); ServiceHost host = new ServiceHost( typeof (DDJService)); ServiceEndpoint serviceEndpoint = host.AddServiceEndpoint( typeof (IDDJService), bindingObject, "http://localhost:1234/DDJService" ); host.Open(); |
You can also create a custom binding element class that derives from the
BindingCollectionElement
abstract base class so that you can specify the custom binding using configuration. Here is how this class might look:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ServiceModel.Channels; using System.ServiceModel.Configuration; namespace DDJService { public class DDJSecureBindingCollectionElement : BindingCollectionElement { public override Type BindingType { get { return typeof (DDJSecureBinding); } } public override ReadOnlyCollection<IBindingConfigurationElement> ConfiguredBindings { get { return new ReadOnlyCollection<IBindingConfigurationElement>( new List<IBindingConfigurationElement>()); } } protected override Binding GetDefault() { return new DDJSecureBinding(); } } } |
Here's how you can configure your service using the service configuration file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| < system.serviceModel > < services > < service name = "DDJService" > binding = "DDJSecureBinding" contract = "IDDJService" > </ endpoint > </ service > </ services > < extensions > < bindingExtensions > < add name = "DDJSecureBinding" type="DDJService.DDJSecureBindingCollectionElement, CustomBinding, Version = 1 .0.0.0, Culture = neutral , PublicKeyToken = null " /> </ bindingExtensions > </ extensions > </ system.serviceModel > |
You can also leverage the
CustomBinding
class of theSystem.ServiceModel.Channels.Binding
namespace to create custom binding for your service:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| using (ServiceHost serviceHost = new ServiceHost ( typeof (DDJService), serviceAddress)) { ReliableSessionBindingElement reliableSession = new ReliableSessionBindingElement(); reliableSession.Ordered = true ; HttpTransportBindingElement httpTransportBindingElement = new HttpTransportBindingElement(); httpTransportBindingElement.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous; httpTransportBindingElement.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; CustomBinding bindingObject = new CustomBinding(reliableSession, httpTransportBindingElement); serviceHost.AddServiceEndpoint( typeof (IDDJService), bindingObject, String.Empty); ServiceMetadataBehavior serviceMetadataBehavior = new ServiceMetadataBehavior(); serviceMetadataBehavior.HttpGetEnabled = true ; serviceHost.Description.Behaviors.Add(serviceMetadataBehavior); serviceHost.Open(); } |
The following code snippet illustrates how you can implement your own custom binding class by deriving from the
System.ServiceModel.Channels.CustomBinding
class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| public class DDJCustomHttpBinding : CustomBinding { private readonly Boolean IsHttpsEnabled; private readonly Boolean IsBinaryEncodingEnabled; private readonly HttpTransportBindingElement transport; public DDJCustomHttpBinding(Boolean isHttpsEnabled, Boolean isBinaryEncodingEnabled = true ) { this .IsHttpsEnabled = isHttpsEnabled; transport = IsHttpsEnabled ? new HttpsTransportBindingElement() : new HttpTransportBindingElement(); IsBinaryEncodingEnabled = isBinaryEncodingEnabled; } public override BindingElementCollection CreateBindingElements() { BindingElement security; if (IsHttpsEnabled) { security = SecurityBindingElement.CreateSecureConversationBindingElement( SecurityBindingElement.CreateUserNameOverTransportBindingElement()); } else { security = SecurityBindingElement.CreateSecureConversationBindingElement( SecurityBindingElement.CreateUserNameForSslBindingElement( true )); } MessageEncodingBindingElement encodingObject; encodingObject = IsBinaryEncodingEnabled ? (MessageEncodingBindingElement) new BinaryMessageEncodingBindingElement() : new TextMessageEncodingBindingElement(); return new BindingElementCollection( new [] { security, encoding, transport, }); } public long MaxMessageSize { set { transport.MaxReceivedMessageSize = value; transport.MaxBufferSize = ( int )value; } } } |