Channels ▼
RSS

C/C++

Working with Bindings in WCF 4.5


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 is WsHttpBinding 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:

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.

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:

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:

<system.serviceModel>
    <services>
        <service name="DDJService">
            <endpoint address="net.tcp://localhost:1234/IDDJService"
            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 the System.ServiceModel.Channels.Binding namespace to create custom binding for your service:

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;
    serviceMetadataBehavior.HttpGetUrl = new Uri("http://localhost:1234/DDJService");
    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:

 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;
            }
        }
    }

Conclusion

Now, having explored the advanced service contract features of WCF 4.5 (as well as the different types of bindings), and implemented a sample custom binding class, you can easily add more features and customization to WCF's binding framework.


Joydip Kanjilal is an occasional contributor to Dr. Dobb's on Microsoft technologies, and a judge in various categories of the Jolt Awards.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video