Tuesday, December 07, 2010

WCF 4.0 routing

In previous post, I've created the top layer of my application architecture using Unity 2.0 and WCF.
In this post I would like to add the final building block of the application server : "The WCF Router service".
WCF routing is a very cool feature in WCF 4.0 that can provides a method for isolating or encapsulating your services from your client,Exposing it only to a router service that will be responsible for routing the messages to the right service.

Here's how it works:

First we've got our services web application (I've mapped it to port 9000 on my local machine).

<system.serviceModel>
   <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
   <behaviors>
     <serviceBehaviors>
       <behavior name="Service1Behavior">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="true" />
       </behavior>
       <behavior name="Service2Behavior">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="true" />
       </behavior>
     </serviceBehaviors>
   </behaviors>
   <services>
     <service name="Server.WCFServices.Service1">
       <host>
         <baseAddresses>
           <add baseAddress="http://localhost:9000/service1"/>
         </baseAddresses>

Step 1 – Create an end point

Just as you would create an end point in your original service, an end point should be declared here.
<endpoint address="service1"
                 binding="basicHttpBinding"
                 name="service1EndPoint"
                 contract="System.ServiceModel.Routing.IRequestReplyRouter" />
<endpoint address="service2"
                 binding="basicHttpBinding"
                 name="service2EndPoint"
                 contract="System.ServiceModel.Routing.IRequestReplyRouter" />


Step 2 – Create an client end point

you should create a client end point in the same way, you would do this on a client application:
<client>
     <endpoint name="service1ClientEndPoint"
               address="http://localhost:9000/service1.svc"
               binding="basicHttpBinding"
               contract="*" />
     <endpoint name="service2ClientEndPoint"
               address="http://localhost:9000/service2.svc"
               binding="basicHttpBinding"
               contract="*" />
</client>

Step 3 – Add a filter

Filters is where the magic happens. Its where the router service knows how to handle an end point and how to filter it.
There are several filter types you could use, you can read more regarding routing filter here.
For this example, I've chosen to use an end point name filter.
<filters>
       <filter name="Service1Filter" filterType="EndpointName" filterData="service1EndPoint"/>
       <filter name="Service2Filter" filterType="EndpointName" filterData="service2EndPoint"/>
</filters>

Step 4 – Add the filter to a filter table

Filters in the filters table map filters to the client end point and therefore creates the final connection to the service itself.
<filterTables>
       <filterTable name="filterTable1">
         <!--add the filters to the message filter table-->
         <!--we determine this through the endpoint name, or through the address prefix-->
         <add filterName="Service1Filter" endpointName="service1ClientEndPoint" priority="1"/>
         <add filterName="Service2Filter" endpointName="service2ClientEndPoint" priority="1"/>
         <!--if none of the other filters have matched, this message showed up on the default router endpoint, with no custom header-->
       </filterTable>
</filterTables>


You can sum up the routing process like this :
End point -> filter -> filter table -> Client end point

Read more: Gadi Berqowitz's Blog