Click here to Skip to main content
Click here to Skip to main content

Getting Started with WCF 4.0 Routing Service

, 17 Jul 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
Introduction to WCF 4.0 Routing Service

Introduction

Routing is the process of picking and directs messages to the proper endpoints through transitional. That is, the purpose of the Routing Service is to receive messages from clients and frontward those messages to the suitable downstream services. Downstream services may be hosted on the same machine or distributed across several machines in a server farm. Routing provides the facility of isolating these services directly accessible from the client application through router. Client applications have knowledge of only one service which further routes request from the client to the specific service.

WCF 4.0 introduces a new service called Routing Service that acts as a message router which has a built-in way for routing WCF service calls. This Routing Service is available under the new assembly System.ServiceModel.Routing. If you want to know more about this, please have a look at this link [^].

In the above figure, the Client application has knowledge of WCF Routing Service which further routes request to the specific services, WCF Service1 or WCF Service2 or WCF Service3.

WCF Routing Service

WCF supplies a class for routing called RoutingService which is located underneath the namespace System.ServiceModel.Routing. These services can be hosted in any service host available EXEs, Windows Services or IIS. When you configure routing service, you need to configure routing service endpoint (Address, Binding, Contract) like every other service. Unlike other service contracts, the Routing Service can be configured with any of the contracts listed below. Based on these contracts, the WCF communication channels are established.

  • ISimplexDatagramRouter: Defines the interface required for processing messages from simplex datagram
  • ISimplexSessionRouter: Defines the interface required to process messages from simplex session channels
  • IRequestReplyRouter: Defines the interface required to process messages from request-reply channels
  • IDuplexSessionRouter: Defines the interface required to process messages from duplex session channels

You can get the details of these integrated contracts through this link [^].

Service Configuration

<services>
      <!-- Routing service with endpoint definition -->
      <service name="System.ServiceModel.Routing.RoutingService"
               behaviorConfiguration="routingBehv">
        <endpoint
          address="/hello"
          binding="wsHttpBinding"
          contract="System.ServiceModel.Routing.IRequestReplyRouter"
          name="HelloService"/>
        <endpoint
         address="/oneway"
         binding="basicHttpBinding"
         contract="System.ServiceModel.Routing.ISimplexDatagramRouter"
         name="OneWayService"/>
        <endpoint
         address="net.tcp://localhost:8733/HelloServiceRouter/duplex"
         binding="netTcpBinding"
         contract="System.ServiceModel.Routing.IDuplexSessionRouter"
         name="DuplexService"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:9000/HelloServiceRouter"/>
          </baseAddresses>
        </host>
      </service>
    </services>    

In this configuration section, we see that the service name is System.ServiceModel.Routing.RoutingService and I have specified different endpoint with different contracts provided by the RoutingService. At this point, the services can listen to the incoming request and also need to know what they should do once they have received the request. To do that, we need to enable routine service and configure it accordingly.

Routing Configuration

 <routing>    
      <filters>
        <filter name="HelloServiceFilter" 
        filterType="EndpointName" filterData="HelloService"/>
        <filter name="OneWayServiceFilter" 
        filterType="EndpointName" filterData="OneWayService"/>
        <filter name="DuplexServiceFilter" 
        filterType="EndpointName" filterData="DuplexService"/>
      </filters>
      <filterTables>
       <filterTable name="filters">
          <add filterName="HelloServiceFilter" 
          endpointName="HelloService" />
          <add filterName="OneWayServiceFilter" 
          endpointName="OneWayService"/>
          <add filterName="DuplexServiceFilter" 
          endpointName="DuplexService"/>
        </filterTable>
      </filterTables>
    </routing> 

The routing section consists of two sections, filters and filterTables. All the filters that are created for the routing are located in the filters section. For each filter, we have to specify the name and the type. Here, the filterData is EndpointName. There are some different kind of filter types available:

  • EndpointName: A custom message filter for use solely in the Routing Service, which filters messages based on the name of the service endpoint.
  • XPath: Used to match header or body elements to a particular value.
  • Action: Used to route based on the SOAP action of a message.
  • And: Used to combine filters before a match can be satisfied.
  • Custom: Used to supply a custom filtering component where you have programmatic control of the filter result.

Here you will get the details explanation about the filter types.

In the above configuration section specially in filterTable section, we also observe that filterName=”HelloServiceFilter” that will match with the name in filter section. The endpointName points to clients configuration. That is, if the endpointName is “HelloService”, it means that there is a client configuration section that maps with this name. As an example:

  <endpoint address="http://localhost:8732/HelloWorldService/HelloService/"
                binding="wsHttpBinding"
                contract="*"
                name="HelloService"/> 

Client Configuration

Finally, we need to specify the endpoint to call when a message passes the filter.

 <client>
      <endpoint address="http://localhost:8732/HelloWorldService/HelloService/"
                binding="wsHttpBinding"
                contract="*"
                name="HelloService"/>
      <endpoint address="http://localhost:8732/OneWayService/"
                binding="basicHttpBinding"
                contract="*"
                name="OneWayService"/>
      <endpoint address="net.tcp://localhost:8734/DuplexService/"
                binding="netTcpBinding"
                contract="*"
                name="DuplexService"/>
    </client>

Here “*” refers to all the Matches contract. That's it. Now let's move into the code portion.

Using the Code

The solution contains three projects for the services, namely HelloWorldService, OneWayService and DuplexService, one is for Client and two for Server (one is for Self Hosting and the other is for IIS Hosting). So the solution structure is like that:

The service contract for HelloWorld Service:

    [ServiceContract]
    public interface IHelloService
    {
        [OperationContract]
        string SayHi(string msg);
    } 

For OneWayService:

 [ServiceContract]
    public interface IHelloService
    { 
        [OperationContract(IsOneWay = true)]
        void SayHi(string msg);
    } 

For DuplexService:

    [ServiceContract(CallbackContract = 
typeof(ICallbackDuplexService), SessionMode = SessionMode.Required)]   
    public interface IHelloService
    {
        [OperationContract]
        string SayHi(string msg);
    } 

Callback Contract:

 public interface ICallbackDuplexService
    {
        [OperationContract]
        string Reply(string msg);
    } 

If you want to know how WCF Callback works, please have a look at this link [^].

Client Code

If you want to use self hosting, then please use this code portion:

Console.WriteLine("************ Self Hosting**************");

            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("\n\n Binding = WSHttpBinding");
            Console.WriteLine("\n\n endpoint = http://localhost:9000/HelloServiceRouter/hello");

            var binding = new WSHttpBinding();
            var endpoint = new EndpointAddress("http://localhost:9000/HelloServiceRouter/hello");
            var proxy = ChannelFactory<IHelloService>.CreateChannel(binding, endpoint);
        
            Console.WriteLine("\n\n Reply from Server :" + proxy.SayHi("Hi"));
            Console.WriteLine("\n\n------------------------------------------------------");

            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("\n\n Binding = NetTcpBinding");
            Console.WriteLine("\n\n endpoint = 
            net.tcp://localhost:8733/HelloServiceRouter/duplex");
            var callback = new MyClientCallback();
            InstanceContext ctx = new InstanceContext(callback);

            var netbinding = new NetTcpBinding();
            var netendpoint = new EndpointAddress
            ("net.tcp://localhost:8733/HelloServiceRouter/duplex");
            var netproxy = DuplexChannelFactory<Rashim.RND.
            WCFRouting.DuplexService.IHelloService>.CreateChannel(ctx, netbinding, netendpoint);
            
            Console.WriteLine("\n\n Reply from the Server:" + netproxy.SayHi("Hi"));
            Console.WriteLine("\n\n------------------------------------------------------");

            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("\n\n Binding = BasicHttpBinding");
            Console.WriteLine("\n\n endpoint = 
            http://localhost:9000/HelloServiceRouter/oneway");
            var onewaybinding = new BasicHttpBinding();
            var onewaynetendpoint = new EndpointAddress
            ("http://localhost:9000/HelloServiceRouter/oneway");
            var onewaynetproxy = ChannelFactory<Rashim.RND.
            WCFRouting.OneWayService.IHelloService>.CreateChannel(onewaybinding, onewaynetendpoint);
            onewaynetproxy.SayHi("Hi");
           
            Console.WriteLine("\n\n oneway binding is working");
            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("************ ++++++++++++++++**************"); 

If you want to use IIS hosting, then you might use this code portion. In my case, I have used the local webserver.

   Console.WriteLine("************ IIS Hosting**************");
            
            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("\n\n Binding = WSHttpBinding");
            Console.WriteLine("\n\n endpoint = http://localhost:5725/RouterService.svc/hello");

            var binding = new WSHttpBinding();
            var endpoint = new EndpointAddress("http://localhost:5725/RouterService.svc/hello");
            var proxy = ChannelFactory<IHelloService>.CreateChannel(binding, endpoint);
            Console.WriteLine("\n\n Reply from Server :" + proxy.SayHi("Hi"));
            Console.WriteLine("\n\n------------------------------------------------------");



            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("\n\n Binding = WSDualHttpBinding");
            Console.WriteLine("\n\n endpoint = http://localhost:5725/RouterService.svc/duplex");          

            var callback = new MyClientCallback();
            InstanceContext ctx = new InstanceContext(callback);

            var netbinding = new WSDualHttpBinding();
            var netendpoint = new EndpointAddress("http://localhost:5725/RouterService.svc/duplex");
            var netproxy = DuplexChannelFactory<Rashim.RND.WCFRouting.
            DuplexService.IHelloService>.CreateChannel(ctx, netbinding, netendpoint);

            Console.WriteLine("\n\n Reply from the Server:" + netproxy.SayHi("Hi"));
            Console.WriteLine("\n\n------------------------------------------------------");

            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("\n\n Binding = BasicHttpBinding");
            Console.WriteLine("\n\n endpoint = http://localhost:9000/HelloServiceRouter/oneway");

            var onewaybinding = new BasicHttpBinding();
            var onewaynetendpoint = new EndpointAddress("http://localhost:5725/RouterService.svc/oneway");
            var onewaynetproxy = ChannelFactory<Rashim.RND.WCFRouting.
            OneWayService.IHelloService>.CreateChannel(onewaybinding, onewaynetendpoint);
            Console.WriteLine("\n\n oneway binding is working");
            Console.WriteLine("\n\n------------------------------------------------------");
            Console.WriteLine("************ ++++++++++++++++**************");    

NOTE: In Rashim.RND.WCFRouting.DuplexService, there are two configuration sections for netTcpBinding and wsDualHttpBinding. If you want to use Rashim.RND.WCFRouting.Router, please comment out the netTcpBinding configuration sections, otherwise comment out the wsDualHttpBinding configuration section.

Okay, now everything is ready right!!

What Else

Run the project Rashim.RND.WCFRouting.Router. You might need to run it as admin mode (Better if you run the EXE as an Admin). And then, run the project Rashim.RND.WCFRouting.Client by commenting out the Self hosting portion in Program.cs. You can also use RouterHostingInIIS. If you want to use RouterHostingInIIS, you need to run the RouterHostingInIIS project and then run the Rashim.RND.WCFRouting.Client by commenting out the specific IIS hosting code portion in Program.cs. Or you might set up the RouterService.svc in IIS and then change the configuration file accordingly.

That's It

That's it for now. I hope this article and the result will help you to start working with WCF 4.0 Routine Service. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Md. Rashim uddin
Software Developer (Senior) KAZ Software Limited.
Bangladesh Bangladesh
I am a true visionary as well as have always been passionate about learning. I always love to work with thought-provoking personnel to develop amazing, exciting and innovative ideas as part of an aggressive team that challenges my ingenious ideas, creativeness and extensive experience.
 
My Blog: http://rashimuddin.wordpress.com/
 
My Email: rashimiiuc at yahoo dot com
Follow on   Twitter   LinkedIn

Comments and Discussions

 
QuestionExcellent PinmemberMusthafa (Member 379898)7-Nov-12 21:49 
Questionadmirable PinmemberAlireza_136220-Jul-12 23:19 
GeneralMy vote of 4 PinmemberSaiyed Alam18-Jul-12 10:03 
GeneralMy vote of 5 Pinmemberdexterama18-Jul-12 3:32 
GeneralRe: My vote of 5 PinmemberMd. Rashim uddin18-Jul-12 3:42 
GeneralMy vote of 5 PinmemberMahmud Hasan17-Jul-12 23:55 
GeneralRe: My vote of 5 PinmemberMd. Rashim uddin18-Jul-12 0:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141030.1 | Last Updated 18 Jul 2012
Article Copyright 2012 by Md. Rashim uddin
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid