[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.
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:
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.
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.
Posted by: generic viagra | 04/27/2010 at 12:07 AM
http://www.rapidsloth.com
Posted by: Harry | 05/26/2010 at 03:29 PM
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.
Posted by: Jordan 2010 | 06/05/2010 at 03:31 AM
I love that any comment of difficult try my blog. Thank you
Posted by: Rerto Jordans | 06/09/2010 at 03:22 AM
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.
Posted by: Generic Viagra | 06/10/2010 at 10:16 AM
This is a great blog.I wonder how typepad is motivating people to make such good blogs.Keep sharing stuff like this.
Posted by: Kamagra Online | 06/11/2010 at 08:05 AM
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!
Posted by: coach handbags | 07/18/2010 at 02:26 AM
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!
Posted by: Nike Dunk High Premium | 08/10/2010 at 08:41 AM
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
Posted by: Retro Jordans | 08/16/2010 at 10:52 AM
Your article written by a high standard! This is a very serious person should treat people living it
Posted by: Nike Dunks | 08/16/2010 at 12:41 PM
ooh this is exciting! I am going to submit... :) Good luck to all the applicants, I can't wait to see who is chosen!
Posted by: nike shox rivalry | 09/07/2010 at 11:52 AM
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.....
Posted by: jordan 10 | 09/17/2010 at 09:08 AM
It is so not good service .just once time ,no more again .
Posted by: wholesaledunk | 09/17/2010 at 09:35 AM
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.....
Posted by: Original Retro Jordan shoes | 09/17/2010 at 10:35 AM
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?
Posted by: Nike Vandal | 09/20/2010 at 05:11 AM
The poor is hated by his neighbour, but the rich hath many friends.
Posted by: jordan retro 9 | 09/27/2010 at 04:20 AM
Welcome to our shop, there are many watches. The watch is top quality, get a watch now!
Posted by: swatch watches | 09/27/2010 at 10:22 AM
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.
Posted by: UGG 5235 boots | 09/28/2010 at 05:28 AM
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.
Posted by: Nike Air Max 95 | 09/29/2010 at 05:19 AM
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.
Posted by: Nike Air Max TN | 09/30/2010 at 02:27 AM
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.
Posted by: air jordans | 10/06/2010 at 04:09 AM
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.
Posted by: Jordan Spizike | 10/06/2010 at 06:04 AM
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.
Posted by: MorrisTabitha33 | 10/11/2010 at 07:05 PM
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.
Posted by: ugg 5819 | 10/15/2010 at 04:06 AM
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'
Posted by: Cortadillo0815 | 10/19/2010 at 11:43 AM