Sunday, October 28, 2012

WCF Endpoints and Bindings Explained

My last post was about netTcpBinding in WCF and I thought it's better if I write a more detailed post about endpoints and bindings in WCF.

Windows Communication Foundation gives us the ability to transmit messages using different transport protocols such as HTTP, TCP, and MSMQ (Microsoft Message Queuing) etc. As you already know all communication with a WCF service occurs through the endpoints of the service.

There can be more than one endpoint for a service (Multiple Endpoints) and these endpoints provide client's the access to functionality offered by a WCF service. These endpoints has many properties and there are three main attributes which are commonly known as ABC’s or Where, How and What of a service. The ABCs make up an endpoint in WCF and these endpoints need to be set for both the service and the client.
  1. Address : The address uniquely identifies the endpoint and tells where the service is located.
  2. Binding : The binding specifies how to communicate with the endpoint. This includes the transport protocol, encoding to use for the messages and the necessary security requirements.
  3. Contract : The contract outlines what functionality the endpoint exposes to the client.
Today I will be focusing on the Address and the Binding attributes, because these two are very important.

For demonstration purposes I have created a WCF Service Application which is “WCFBindingApp” and I am using the IIS and not the Visual Studio Development server to host my service. Because we can’t use TCP bindings for services which are hosted in Visual Studio Development Server.

IService1

using System.ServiceModel;

namespace WcfBindingApp
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string MyMethod(string s);
    }
}

Service1.svc.cs

namespace WcfBindingApp
{
    public class Service1 : IService1
    {
        public string MyMethod(string s)
        {
            return string.Format("Message From Client: {0}", s);
        }
    }
}

Address of a Endpoint

When we define endpoints for a service, there are numerous options for specifying the address. You can either use the IP address or the host name along with the port number. If no port number is mentioned the default port for the protocol is used. There are two techniques we can use to specify the address.

   1.   Specify the absolute address for each endpoint

<services>        
    <service name="WcfBindingApp.Service1">        
        <endpoint address="http://localhost/WcfBindingApp/Service.svc" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
    </service>
</services>

    2.   Specify a base address and then specify relative address for each endpoint

<services>
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>

        <host>
            <baseAddresses>
                <add baseAddress="http://localhost/WcfBindingApp/Service.svc" />
            </baseAddresses>
        </host>
    </service>
</services>

since I am using the IIS here, I can write it even in this way without mentioning the base address (the base address will be determined by the IIS virtual directory). This will also work.

<services> 
    <!-- base address determined by IIS virtual directory -->        
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>
    </service>
</services>

There are couple of things you should know when you define the address.

 1. If the address is empty, you can omit the address attribute. This means the endpoint will be exposed via the base address.

<endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>

is same as,

<endpoint binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>

2. As I said before, when hosting in IIS, you don’t have to mention the base address. The base HTTP address is determined by the IIS virtual directory and WCF  ignores any base addresses we may specify.

3. When hosting in IIS, if you do specify an absolute address for a particular endpoint, it must start with the base address corresponding to the virtual directory.

4. When exposing multiple endpoints with same contract and with different bindings, each endpoint address must be unique.

5. If multiple endpoints share the same binding with different contracts, you can use the same address across those endpoints.

6. You can have multiple base addresses for each service, but only one for each protocol.

Bindings of a Endpoint

The bindings is the key element of the WCF architecture. There are variety types of bindings available to use when defining endpoints.

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. Following image shows all the binding classes which are available with WCF.

image
Binding class which are available out of the box
In here I will only list the features of most used ones.
  • basicHttpBinding
    • Designed for scenarios where interoperability is of utmost importance.
    • HTTP for the transport and text for the message encoding.
    • Message version is SOAP 1.1.
    • Capable of using transport or message security, but both are disabled by default.
  • wsHttpBinding
    • Designed for interoperability while incorporating with richer Web services protocols for security, reliable messaging, and transaction.
    • Message version is SOAP 1.2.
    • This is default binding in WCF.
  • wsDualHttpBinding
    • Supports all the feature of wsHttpBinding.
    • Used for Duplex service contracts.
    • Supports bidirectional communication.
  • netTCPBinding
    • Unlike the ws* specific bindings, the various "Net" bindings were not designed for interoperability. This explains why the binding names are prefixed with "Net"
    • Assumes you have the Microsoft .NET Framework 3.0 installed on both sides.
    • NetTcpBinding uses TCP for the transport, binary for the message encoding, and SOAP 1.2 for the message version.
    • Enables transport security by default and can support transactions if enabled.
  • netPeerTCPBinding
    • Provides a secure binding for peer-to-peer network applications.
  • netNamedPipeBinding
    • Provides a secure and reliable binding that is optimized for on-machine communication.
    • Can be only used over a single WCF computer.
  • netMSMQBinding
    • Represents a queued binding that is suitable for cross-machine communication.
  • CustomBinding
Transport Protocols

Not like XML web services, WCF supports any protocol to communicate with the clients.
  • Http : This is the chosen protocol for communicating over the web and gives the ability to integrate the service with open standards exposing services to clients on many plaforms.
  • TCP : Fast binary format protocol. A great performance in WCF-WCF communication.
  • Named pipes : Fast communication between the client and the server which runs on the same machine. Works only in WCF-WCF.
  • MSMQ : Microsoft Message Queue allows queuing of messages and very useful in disconnected communications between the client the server. Used when client wants to enqueue a message that a service can consume later.
  • Custom Protocols : Can define own protocols.
Now let’s move in to see how binding is specified in the configuration file. The basic way is as follows.

<services>
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" contract="WcfBindingApp.IService1"></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>

        <host>
            <baseAddresses>
                <add baseAddress="http://localhost/WcfBindingApp/Service.svc" />
            </baseAddresses>
        </host>
    </service>
</services>

Here I have specified three bindings. And default settings are applied to each bindings. Now let’s say you want to change the wsHttpBinding defaults and apply new settings. You can easily do it this way.

<services>
    <service name="WcfBindingApp.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfBindingApp.IService1" ></endpoint>
        <endpoint address="secure" binding="wsHttpBinding" bindingConfiguration="mybinding" contract="WcfBindingApp.IService1"></endpoint>
        <endpoint address="tcp" binding="netTcpBinding" contract="WcfBindingApp.IService1" ></endpoint>

        <host>
            <baseAddresses>
                <add baseAddress="http://localhost/WcfBindingApp/Service.svc" />
            </baseAddresses>
        </host>
    </service>
</services>

<bindings>
    <wsHttpBinding>
        <binding name="mybinding"></binding> <!--you can change the default settings here-->
    </wsHttpBinding>
</bindings>

I am changing the wsHttpBinding settings and giving it a name. And in my endpoint I am giving it as endpoints binding congfiguration.

Now I have a client console application which will communicate with service using different bindings.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (svcTest.Service1Client client = new svcTest.Service1Client("BasicHttpBinding_IService1"))
                {
                    Console.WriteLine(client.MyMethod("basicHttpBinding"));
                }
                using (svcTest.Service1Client client = new svcTest.Service1Client("WSHttpBinding_IService1"))
                {
                    Console.WriteLine(client.MyMethod("wsHttpBinding"));
                }
                using (svcTest.Service1Client client = new svcTest.Service1Client("nettcpbinding_iservice1"))
                {
                    Console.WriteLine(client.MyMethod("netTcpBinding"));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error:{0}", ex);
            }
            Console.ReadLine();
        }
    }
}

And when I run this I will get the output as follows.
Output
Hope you all got a good understanding about endpoints and different bindings I have explained. Appreciating your feedback.

Happy Coding.

Regards,
Jaliya

2 comments: