[What's new in WCF4] Discovery announcements - or: "Look ma: I can see when my service goes online or offline!"
[What's new in WCF4] Protocol bridging & fault tolerance with the Routing Service - or: "Look ma: Really just one service to talk to!"

[What's new in WCF4] Routing Service - or: "Look ma: Just one service to talk to!"


[Note: all the information was gathered based on a close-to-Beta 1 build of .NET Framework 4.0 and Visual Studio 2010. Details may vary and change]

The Intermediate Routing pattern is a well understood pattern. Some people apply it to have just one service entry point with a universal contract and then route incoming messages to the appropriate business services.
Others use it to determine the path of a message within a system, which means there can be a cascade of routers each responsible for different aspects of routing messages.
WCF was always a bit short in this respect. Sure, there are numerous implementations based on WCF 3.x (just Google...), just recently Dominick and myself implemented something like this for a customer. But there is nothing that came straight in the core platform. This now changes with WCF4.

There is a generic routing service in WCF4 which enables routing for diiferent message exchange patterns (MEPs). The responsible class is System.ServiceModel.Routing.RoutingService.

WCF4 Routing Service

As we can see this service implements four different contracts to fulfill different MEPs and session semantics. If we want to host a routing service we do not need a lot of work, just host it (like this for a self-hosted case):

ServiceHost serviceHost = new ServiceHost(typeof(RoutingService));

try
{
    serviceHost.Open();
    Console.WriteLine("WCF Routing Service running...");
    Console.WriteLine("Press <ENTER> to terminate router.");

    Console.ReadLine();
    serviceHost.Close();
}
catch (CommunicationException)
{
    serviceHost.Abort();
}

        
OK, easy.
Each of the contracts RoutingService implements represent the universal contract pattern (Message in, Message out, or just Message in for the one-way case). WCF4 always uses the async operation pattern, which totally makes sense as we have bound I/O happening in the routing service:

[ServiceContract(SessionMode=SessionMode.Allowed)]
public interface ISimplexDatagramRouter
{
    [OperationContract(AsyncPattern=true, IsOneWay=true, Action="*")]
    IAsyncResult BeginProcessMessage(Message message, AsyncCallback callback, object state);
    void EndProcessMessage(IAsyncResult result);
}

[ServiceContract(SessionMode=SessionMode.Required)]
public interface ISimplexSessionRouter
{
    [OperationContract(AsyncPattern=true, IsOneWay=true, Action="*")]
    IAsyncResult BeginProcessMessage(Message message, AsyncCallback callback, object state);
    void EndProcessMessage(IAsyncResult result);
}

[ServiceContract(SessionMode=SessionMode.Allowed)]
public interface IRequestReplyRouter
{
    [OperationContract(AsyncPattern=true, IsOneWay=false, Action="*", ReplyAction="*"), GenericTransactionFlow(TransactionFlowOption.Allowed)]
    IAsyncResult BeginProcessRequest(Message message, AsyncCallback callback, object state);
    Message EndProcessRequest(IAsyncResult result);
}

[ServiceContract(SessionMode=SessionMode.Required, CallbackContract=typeof(IDuplexRouterCallback))]
public interface IDuplexSessionRouter
{
    [OperationContract(AsyncPattern=true, IsOneWay=true, Action="*"), GenericTransactionFlow(TransactionFlowOption.Allowed)]
    IAsyncResult BeginProcessMessage(Message message, AsyncCallback callback, object state);
    void EndProcessMessage(IAsyncResult result);
}

[ServiceContract(SessionMode=SessionMode.Allowed)]
internal interface IDuplexRouterCallback
{
    [OperationContract(AsyncPattern=true, IsOneWay=true, Action="*"), GenericTransactionFlow(TransactionFlowOption.Allowed)]
    IAsyncResult BeginProcessMessage(Message message, AsyncCallback callback, object state);
    void EndProcessMessage(IAsyncResult result);
}

Pure love :)

So, that was for the WCF infrastructure geek - but how do we actually route? What do we route?
Enter message filters.
The routing service in WCF4 uses message filters in order to route messages. Message filters have always been in WCF since the first version and just now have a prominent role and also got some new filters. This is the list of available message filters:

WCF4 Message Filters

For a first rendezvous with routing we will just use the MatchAllMessageFilter. This filter just returns true and does not do any logic in the Match() method and thus is a pass-through filter.
Message filter will be used inside entries in a RoutingTable. These entries specify which endpoint to call from the RoutingService when the given MessageFilter returns true. The routing table is configured as a service behavior.
Here is a sample config implementing the just explained stuff:
        
<configuration>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="routingData"
          name="System.ServiceModel.Routing.RoutingService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:7777/Services/Universal"/>
          </baseAddresses>
        </host>

        <endpoint address=""
                  binding="basicHttpBinding"
                  name="requestReplyEndpoint"
                  contract="System.ServiceModel.Routing.IRequestReplyRouter" />
      </service>
    </services>
    
    <behaviors>
      <serviceBehaviors>        
        <behavior name="routingData">
          <serviceMetadata httpGetEnabled="True"/>          
          <routing routingTableName="mainRoutingTable" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
    <client>
      <endpoint name="HelloService" address="http://localhost:7777/Services/Hello" binding="basicHttpBinding" contract="*" />
    </client>
    
    <routing>
      <filters>
        <filter name="MatchAllFilter" filterType="MatchAll" />
      </filters>      
      <routingTables>
        <table name="mainRoutingTable">
          <entries>
            <add filterName="MatchAllFilter" endpointName="HelloService" />
          </entries>
        </table>
      </routingTables>
    </routing>

  </system.serviceModel>
</configuration>

This means we expose an IRequestReplyRouter with basicHttpBinding at http://localhost:7777/Services/Universal to the consumers. As a final target service we just have one service (our beloved HelloService) and its endpoint is defined in the <client> section.
Based on the message filter which is referenced through an entry in the routing table the messages being sent to our routing endpoint will be routed through to our HelloService.
Admittedly, this sample is not really real-worldish :) But it should give a first understanding of the RoutingService in WCF4.

To make the whole picture complete, we will let our client/consumer just talk to the routing endpoint - the client does not know anything about the HelloService (besides the contract of course).

<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:7777/Services/Universal"
                binding="basicHttpBinding"
                contract="IHelloService" />
    </client>   
  </system.serviceModel>
</configuration>

Please note that until now we just do plain routing in the sense of message dispatching. We can not do message transformations (yet). This should be covered in a future post, though.

But let's look at two more message filters, the ActionMessageFilter and the XPathMessageFilter, which both come in very handy for typical routing scenarios.
The ActionMessageFilter checks whether a given action value is fulfilled for the incoming message. Likewise, the XPathMessageFilter checks whether a given XPath expression is true for an incoming message. Usually, the XPath filter needs namespace table entries for managing XML namespaces.
In order to use either of these filters to route our client messages to the HelloService we can change the filters and routing table configuration like this:

<routing>
  <filters>
    <!--<filter name="action1" filterType="Action" filterData="http://tempuri.org/IHelloService/SayIt" />-->
    <filter name="xPath1" filterType="XPath" filterData="/s:Envelope/s:Header/wsa:Action = 'http://tempuri.org/IHelloService/SayIt'" />
  </filters>
  <routingTables>
    <table name="mainRoutingTable">
      <entries>
        <!--<add filterName="action1" endpointName="HelloService" />-->
        <add filterName="xPath1" endpointName="HelloService" />
      </entries>
    </table>
  </routingTables>
  <namespaceTable>
    <add prefix="s" namespace="http://schemas.xmlsoap.org/soap/envelope/" />
    <add prefix="wsa" namespace="http://schemas.microsoft.com/ws/2005/05/addressing/none" />
  </namespaceTable>
  <alternateEndpoints>        
  </alternateEndpoints>
</routing>

The two filter configurations are equivalent in their functionailty based on the given filter data values.
Pretty straight.forward, IMO.

One more thing: if the originally specified endpoint in a routing table entry cannot be reached then the list of alternate endpoints is checked (OK, in our sample it is empty, but you get the idea) and the routing service logic tries to call them.

Honestly, I can see a number of customers embracing this new feature (and in this post I was just scratching the surface).

OK; that's it for now for a first introduction to the routing capabilities in WCF4.
Stay tuned for more.


Comments

Feed You can follow this conversation by subscribing to the comment feed for this post.

generic viagra

I am trying to open up a port on my firewall to boost my connection to
the internet. For uTorrent, actually. I have both a 2Wire (HomePortal
1100 if that matters) DSL modem that is connected, via Ethernet cable,
to a Motorola WR850G wireless router. This setup has enabled those of
us in my apartment to enjoy the benefits of a wireless network with
semi-wild abandon.

Harry

http://www.rapidsloth.com

Jordan 2010

Benjamin Franklin says that "Early to bed and early to rise, makes a man healthy, wealthy, and wise". So, develop a good habit, then execute it.

Rerto Jordans

I love that any comment of difficult try my blog. Thank you

Generic Viagra

Thanks for sharing .Keep posting articles like this.A good example of content presentation.A piece of information from you every now and then is really great.Great article post.I appreciate your writing skills.They are excellent.The knowledge of the subject is pretty good.To post an article on any topic it takes a great effort and knowledge to have proper knowledge of the niche.

Kamagra Online

This is a great blog.I wonder how typepad is motivating people to make such good blogs.Keep sharing stuff like this.

coach handbags

In your blog I feel your enthusiasm for life. Thank you for sharing ! I learned a lot! May the joy and happiness around you today and always.By the way,Do you like coach handbags? It will make your life different!

Nike Dunk High Premium

I will be asked to do everything the best I think! Can read your blog with my own than I found too much difference! I admire you!

Retro Jordans

Every single site I've gone to to research this company has some person complaining about the statistics/information, yet no one has provided information to contradict what was presented. If you feel the information is wrong, then please tell us where to find the correct information
Our store offers you all kinds of favourite products like Adidas World Cup 2010 Shoes

Nike Dunks

Your article written by a high standard! This is a very serious person should treat people living it

nike shox rivalry

ooh this is exciting! I am going to submit... :) Good luck to all the applicants, I can't wait to see who is chosen!

jordan 10

Life is ordinary,and everyone are searching for good life,and if we want to take good life,we must try the best to everything.and please have a look at my website,haha.....

wholesaledunk

It is so not good service .just once time ,no more again .

Original Retro Jordan shoes

Life is ordinary,and everyone are searching for good life,and if we want to take good life,we must try the best to everything.and please have a look at my website,haha.....Life is ordinary,and everyone are searching for good life,and if we want to take good life,we must try the best to everything.and please have a look at my website,haha.....

Nike Vandal

It is authentic that we do not know what we’ve acquired until eventually we shed it, but it is also actual that we really don't know what we’ve been missing till it arrives. Do you imagine so?

jordan retro 9

The poor is hated by his neighbour, but the rich hath many friends.

swatch watches

Welcome to our shop, there are many watches. The watch is top quality, get a watch now!

UGG 5235 boots

Your artilcles are good,I read all yours,I got the best meaning about something,insist in them,and I will follow you in the future,and now can you support me to know about UGG 5235 boots of my website,only need to link my name and know all about it,thanks.

Nike Air Max 95

After reading you blog I learnt a lot.But I do not like that, And reading you blog make me so sad. We will can not reside in the world. Because the temperature become more and more high, But to that time where can we go, So now we must begin to protect the earth.

Nike Air Max TN

We never consistently get our hopes and dreams, and we really do not usually get our individual way.
But really don't surrender hope, since you could make a distinction 1 condition and an individual particular person at a time.

air jordans

Science is not can grow in science, admittedly, except perspiration is no other successful method, Enthusiasm, fantasy, with the whole body to want, cannot replace labor.

Jordan Spizike

I'm glad to see Boeing posted a response and that they will work on doing better, wish though they had thought of it themselves that when a child takes the time to draw a picture and send it to them that Boeing should send out an appropriate response and perhaps a coloring book/stickers to the child.
Now link my name to see something.

MorrisTabitha33

When you are in not good state and have no cash to go out from that, you will have to take the loan. Just because it should aid you unquestionably. I get financial loan every year and feel myself good because of this.

ugg 5819

Put your heart and soul into the things what you do that you will feel more easy than before. This is my idea that carry out many years ago.

Cortadillo0815

hello, nice articles. it helped me understanding framework 4 routing.
how is the routing with using Security and credentials? I don't know how to configurize the router for using clientCredential 'UserName' in security.Mode='Message'

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been saved. Comments are moderated and will not appear until approved by the author. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Comments are moderated, and will not appear until the author has approved them.

Your Information

(Name is required. Email address will not be displayed with the comment.)