- [ServiceContract]
- public interface ITestService
- {
- [OperationContractAttribute]
- public string GetSomeData();
- [OperationContractAttribute]
- public void StoreSomeData();
- }
Bindings in WCF 4.5
Address, Binding, and Contract are commonly referred to as the "ABCs" of WCF. An Address specifies the absolute or relative path or the Uniform Resource Indicator (URI) 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
BasicHttpBinding
BasicHttpBinding is the simplest type of binding used. It provides support for both the HTTP and HTTPS protocol. The following code snippet illustrates how this type of binding can be specified.
- <bindings>
- <basicHttpBinding>
- <binding name="CCRServiceBinding">
- <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.
- <binding name=" CCRServiceBinding ">
- <security mode="TransportWithMessageCredential">
- <transport clientCredentialType="None"/>
- <message clientCredentialType="IssuedToken"/>
- </security>
- </binding>
NetTcpBindingNetTcpBinding 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.
- <client>
- <endpoint name="Sample" address="net.tcp://localhost:1234/CCRService"
- binding="netTcpBinding" contract="ICCRService" >
- <identity>
- <servicePrincipalName value=”CCRService/RamaSagar-PC” />
- </identity>
- </endpoint>
NetNamePipeBindingIn 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 to specify this type of binding for your service:
- <services>
- <service name="CCRService" behaviorConfiguration="CCRService Behavior">
- <host>
- <baseAddresses>
- <add baseAddress="net.pipe://localhost:1234/CCRService "/>
- </baseAddresses>
- </host>
- <endpoint address="" binding="netNamedPipeBinding" contract="ICCRService "></endpoint>
- </service>
- </services>
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 to configure this type of binding.
- <endpoint
- address="net.p2p://localhost:1234/CCRService/"
- binding="netPeerTcpBinding"
- bindingConfiguration="netp2pBinding"
- contract="ICCRService">
- <bindings>
- <netPeerTcpBinding>
- <binding name="netP2P" >
- <resolver mode="Pnrp" />
- <security mode="None" />
- </binding>
- </netPeerTcpBinding>
- </bindings>
WsDualHttpBinding
If you need support for the Duplex Message Exchange (where services can communicate with their clients through callbacks), you need to use WsDualHttpBinding. In essence, it is WsHttpBinding with support for a Duplex Message Exchange pattern.
WsFederationHttpBinding
In WCF, WsFederationHttpBinding is used for federated security.
CustomBinding
We can implement your own custom binding class for additional transport protocols, security and so on. To implement a custom binding class, you need to derive a class from the System.ServiceModel.Channels.Binding class.
- using System.ServiceModel.Channels;
- namespace CCRService
- {
- public class CCRSecureBinding : 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 to configure our custom binding class programmatically.
- CCRSecureBinding bindingObject = new CCRSecureBinding();
- bindingObject.Elements.Add(new BinaryMessageEncodingBindingElement());
- bindingObject.Elements.Add(new HttpTransportBindingElement());
- ServiceHost host = new ServiceHost(typeof(CCRService));
- ServiceEndpoint serviceEndpoint = host.AddServiceEndpoint(typeof(ICCRService), bindingObject, "http://localhost:1234/CCRService");
- host.Open();
We 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.
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Configuration;
- namespace CCRService
- {
- public class CCRSecureBindingCollectionElement
- : BindingCollectionElement
- {
- public override Type BindingType
- {
- get { return typeof(CCRSecureBinding); }
- }
- public override ReadOnlyCollection<IBindingConfigurationElement>
- ConfiguredBindings
- {
- get
- {
- return new ReadOnlyCollection<IBindingConfigurationElement>(
- new List<IBindingConfigurationElement>());
- }
- }
- protected override Binding GetDefault()
- {
- return new CCRSecureBinding();
- }
- }
- }
Here's how to configure your service using the service configuration file.
- <system.serviceModel>
- <services>
- <service name="CCRService">
- <endpoint address="net.tcp://localhost:1234/ICCRService"
- binding="CCRSecureBinding"
- contract="ICCRService">
- </endpoint>
- </service>
- </services>
- <extensions>
- <bindingExtensions>
- <add name="CCRSecureBinding"
- type="CCRService.CCRSecureBindingCollectionElement,
- CustomBinding,
- Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
- </bindingExtensions>
- </extensions>
- </system.serviceModel>
We can also leverage the CustomBinding class of the System.ServiceModel.Channels.Binding namespace to create custom binding for your service:
- using (ServiceHost serviceHost = new ServiceHost (typeof(CCRService), 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(ICCRService), bindingObject, String.Empty);
- ServiceMetadataBehavior serviceMetadataBehavior = new ServiceMetadataBehavior();
- serviceMetadataBehavior.HttpGetEnabled = true;
- serviceMetadataBehavior.HttpGetUrl = new Uri("http://localhost:1234/CCRService");
- serviceHost.Description.Behaviors.Add(serviceMetadataBehavior);
- serviceHost.Open();
- }
The following code snippet illustrates how to implement your own custom binding class by deriving from the System.ServiceModel.Channels.CustomBinding class:
- public class CCRCustomHttpBinding : CustomBinding
- {
- private readonly Boolean IsHttpsEnabled;
- private readonly Boolean IsBinaryEncodingEnabled;
- private readonly HttpTransportBindingElement transport;
- public CCRCustomHttpBinding(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;
- }
- }
- }
Conclusion In this article we saw the advanced service contract features of WCF 4.5 (as well as the various types of bindings) and implemented a sample custom binding class. We can easily add more features and customization to WCF's binding framework.