Bindings in WCF 4.5

Introduction

In this article we will see how to create a service contract base class in C# 5.0. We will discuss the supported bindings in WCF and show how to design and implement your own custom binding class with additional protocols, security and so on for use in WCF 4.5. (To work with the code examples discussed in this article, you should use Visual Studio 2012 or later.)

Service contracts in WCF

Service contracts in WCF are used to expose one or more operations. We can define the operations by creating a method and then use the OperationContractAttribute attribute to expose it. Note that methods that are not decorated with this attribute are not service operations (meaning they are not exposed by your WCF service). While you can use either an interface or a class to design your service contract, using an interface has several advantages.

The following code illustrates an interface-based service contract:

  1. [ServiceContract]  
  2. public interface ITestService  
  3. {  
  4.   [OperationContractAttribute]  
  5.   public string GetSomeData();  
  6.   [OperationContractAttribute]  
  7.   public void StoreSomeData();    
  8. }  

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:

  1. HTTP
  2. TCP
  3. Message Queuing
  4. 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.

  1. <bindings>  
  2.   <basicHttpBinding>  
  3.     <binding name="CCRServiceBinding">  
  4.       <security mode="Transport">  
  5.         <transport clientCredentialType="None"/>  
  6.       </security>  
  7.     </binding>  
  8.   </basicHttpBinding>  
  9. </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. <binding name=" CCRServiceBinding ">  
  2.   <security mode="TransportWithMessageCredential">  
  3.     <transport clientCredentialType="None"/>  
  4.     <message clientCredentialType="IssuedToken"/>  
  5.   </security>  
  6. </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. <client>  
  2.     <endpoint name="Sample" address="net.tcp://localhost:1234/CCRService"  
  3.       binding="netTcpBinding" contract="ICCRService" >  
  4.       <identity>  
  5.         <servicePrincipalName value=”CCRService/RamaSagar-PC” />  
  6.       </identity>  
  7.     </endpoint>  
NetNamePipeBinding

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 to specify this type of binding for your service:
  1. <services>  
  2. <service name="CCRService" behaviorConfiguration="CCRService Behavior">  
  3.         <host>  
  4.           <baseAddresses>  
  5.             <add baseAddress="net.pipe://localhost:1234/CCRService "/>  
  6.           </baseAddresses>  
  7.         </host>  
  8. <endpoint address="" binding="netNamedPipeBinding" contract="ICCRService "></endpoint>  
  9. </service>  
  10. </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.
  1. <endpoint  
  2.   address="net.p2p://localhost:1234/CCRService/"  
  3.   binding="netPeerTcpBinding"   
  4.   bindingConfiguration="netp2pBinding"  
  5.   contract="ICCRService">  
  6.   <bindings>  
  7.         <netPeerTcpBinding>  
  8.           <binding name="netP2P" >  
  9.             <resolver mode="Pnrp" />  
  10.             <security mode="None" />  
  11.           </binding>  
  12.   </netPeerTcpBinding>  
  13. </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.
  1. using System.ServiceModel.Channels;  
  2. namespace CCRService  
  3. {  
  4.     public class CCRSecureBinding : System.ServiceModel.Channels.Binding  
  5.     {  
  6.         private HttpTransportBindingElement transport = new HttpTransportBindingElement();  
  7.         private BinaryMessageEncodingBindingElement encoding = new BinaryMessageEncodingBindingElement();  
  8.         public override BindingElementCollection CreateBindingElements()  
  9.         {  
  10.             BindingElementCollection bindingElements = new BindingElementCollection();  
  11.             bindingElements.Add(this.encoding);  
  12.             bindingElements.Add(this.transport);  
  13.             return bindingElements;  
  14.         }  
  15.         public override string Scheme  
  16.         {  
  17.             get { return this.transport.Scheme; }  
  18.         }  
  19.     }  
  20. }  
The following code illustrates how to configure our custom binding class programmatically.
  1. CCRSecureBinding bindingObject = new CCRSecureBinding();  
  2. bindingObject.Elements.Add(new BinaryMessageEncodingBindingElement());  
  3. bindingObject.Elements.Add(new HttpTransportBindingElement());  
  4. ServiceHost host = new ServiceHost(typeof(CCRService));  
  5. ServiceEndpoint serviceEndpoint = host.AddServiceEndpoint(typeof(ICCRService), bindingObject, "http://localhost:1234/CCRService");  
  6. 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.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Collections.ObjectModel;  
  4. using System.ServiceModel.Channels;  
  5. using System.ServiceModel.Configuration;  
  6. namespace CCRService  
  7. {  
  8.  public class CCRSecureBindingCollectionElement  
  9.         : BindingCollectionElement  
  10.     {  
  11.         public override Type BindingType  
  12.         {  
  13.             get { return typeof(CCRSecureBinding); }  
  14.         }  
  15.         public override ReadOnlyCollection<IBindingConfigurationElement>  
  16.                               ConfiguredBindings  
  17.         {  
  18.             get  
  19.             {  
  20.                 return new ReadOnlyCollection<IBindingConfigurationElement>(  
  21.                 new List<IBindingConfigurationElement>());  
  22.             }  
  23.         }  
  24.         protected override Binding GetDefault()  
  25.         {  
  26.             return new CCRSecureBinding();  
  27.         }  
  28.     }  
  29. }  
Here's how to configure your service using the service configuration file.
  1. <system.serviceModel>  
  2.     <services>  
  3.         <service name="CCRService">  
  4.             <endpoint address="net.tcp://localhost:1234/ICCRService"  
  5.             binding="CCRSecureBinding"  
  6.             contract="ICCRService">  
  7.             </endpoint>  
  8.         </service>  
  9.     </services>  
  10.     <extensions>  
  11.         <bindingExtensions>  
  12.             <add name="CCRSecureBinding"  
  13.                type="CCRService.CCRSecureBindingCollectionElement,  
  14.                CustomBinding,  
  15.                Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />  
  16.         </bindingExtensions>  
  17.     </extensions>  
  18. </system.serviceModel>  
We can also leverage the CustomBinding class of the System.ServiceModel.Channels.Binding namespace to create custom binding for your service:
  1. using (ServiceHost serviceHost = new ServiceHost (typeof(CCRService), serviceAddress))  
  2. {  
  3.     ReliableSessionBindingElement reliableSession = new ReliableSessionBindingElement();  
  4.     reliableSession.Ordered = true;  
  5.     HttpTransportBindingElement httpTransportBindingElement = new HttpTransportBindingElement();  
  6.     httpTransportBindingElement.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;  
  7.     httpTransportBindingElement.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;  
  8.     CustomBinding bindingObject = new CustomBinding(reliableSession, httpTransportBindingElement);  
  9.     serviceHost.AddServiceEndpoint(typeof(ICCRService), bindingObject, String.Empty);  
  10.     ServiceMetadataBehavior serviceMetadataBehavior = new ServiceMetadataBehavior();  
  11.     serviceMetadataBehavior.HttpGetEnabled = true;  
  12.     serviceMetadataBehavior.HttpGetUrl = new Uri("http://localhost:1234/CCRService");  
  13.     serviceHost.Description.Behaviors.Add(serviceMetadataBehavior);  
  14.     serviceHost.Open();  
  15. }  
The following code snippet illustrates how to implement your own custom binding class by deriving from the System.ServiceModel.Channels.CustomBinding class: 
  1. public class CCRCustomHttpBinding : CustomBinding  
  2.    {  
  3.        private readonly Boolean IsHttpsEnabled;  
  4.        private readonly Boolean IsBinaryEncodingEnabled;  
  5.        private readonly HttpTransportBindingElement transport;  
  6.        public CCRCustomHttpBinding(Boolean isHttpsEnabled, Boolean isBinaryEncodingEnabled = true)  
  7.        {  
  8.            this.IsHttpsEnabled = isHttpsEnabled;  
  9.            transport = IsHttpsEnabled ? new HttpsTransportBindingElement() : new HttpTransportBindingElement();  
  10.            IsBinaryEncodingEnabled = isBinaryEncodingEnabled;  
  11.        }         
  12.    
  13.        public override BindingElementCollection CreateBindingElements()  
  14.        {  
  15.            BindingElement security;  
  16.    
  17.            if (IsHttpsEnabled)  
  18.            {  
  19.                security = SecurityBindingElement.CreateSecureConversationBindingElement(  
  20.                    SecurityBindingElement.CreateUserNameOverTransportBindingElement());  
  21.            }  
  22.            else  
  23.            {  
  24.                security = SecurityBindingElement.CreateSecureConversationBindingElement(  
  25.                    SecurityBindingElement.CreateUserNameForSslBindingElement(true));  
  26.            }  
  27.            MessageEncodingBindingElement encodingObject;  
  28.                encodingObject = IsBinaryEncodingEnabled  
  29.                            ? (MessageEncodingBindingElement)new BinaryMessageEncodingBindingElement()  
  30.                            : new TextMessageEncodingBindingElement();  
  31.            return new BindingElementCollection(new[]  
  32.            {  
  33.                security,  
  34.                encoding,  
  35.                transport,  
  36.            });  
  37.        }  
  38.        public long MaxMessageSize  
  39.        {  
  40.            set  
  41.            {  
  42.                transport.MaxReceivedMessageSize = value;  
  43.                transport.MaxBufferSize = (int)value;  
  44.            }  
  45.        }  
  46.    }  
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.