WCF 4.0 routing

6 בדצמבר 2010

2 comments

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>
</
host>
<
endpoint address="" binding="basicHttpBinding" contract="Common.Contracts.IService1"/>
<
endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</
service>
<
service name="Server.WCFServices.Servicew">
<
host>
<
baseAddresses>
<
add baseAddress="http://localhost:9000/service2"/>
</
baseAddresses>
</
host>
<
endpoint address="" binding="basicHttpBinding" contract="Common.Contracts.IService2"/>
<
endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</
service>
</
services>
</
system.serviceModel>

You can notice I've got 2 services : service1 and service2.

Now you should create a new web application that will host the router service (I've mapped it to port 8689 on my local machine)

This web application project holds the router.svc file and a web configuration file.

You should follow these steps to set up your service in the router configuration:

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

Here's the entire web configuration file :

<system.serviceModel>
<
services>
<
service behaviorConfiguration="routingConfiguration"
name="System.ServiceModel.Routing.RoutingService">
<
host>
<
baseAddresses>
<
add baseAddress="http://localhost:8689/router.svc" />
</
baseAddresses>
</
host>
<!--
Set up the inbound endpoints for the Routing Service-->
<!--
first create the general router endpoint-->
<
endpoint address="general"
binding="basicHttpBinding"
name="routerEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />
<!--
create a virtual endpoint for the the regular calculator service-->
<
endpoint address="service1"
binding="basicHttpBinding"
name="service1EndPoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />

<
endpoint address="service2"
binding="basicHttpBinding"
name="service2EndPoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />

</
service>
</
services>
<
behaviors>
<!--
default routing service behavior definition-->
<
serviceBehaviors>
<
behavior name="routingConfiguration">
<
routing filterTableName="filterTable1" />
<
serviceMetadata httpGetEnabled="true"/>
<
serviceDebug includeExceptionDetailInFaults="true" />
</
behavior>
</
serviceBehaviors>
</
behaviors>

<
client>
<!--
set up the destination endpoints-->
<
endpoint name="service1ClientEndPoint"
address="http://localhost:9000/service1.svc"
binding="basicHttpBinding"
contract="*" />

<!--
set up the destination endpoints-->
<
endpoint name="service2ClientEndPoint"
address="http://localhost:9000/service2.svc"
binding="basicHttpBinding"
contract="*" />
</
client>
<
routing>
<
filters>
<
filter name="Service1Filter" filterType="EndpointName" filterData="service1EndPoint"/>
<
filter name="Service2Filter" filterType="EndpointName" filterData="service2EndPoint"/>
</
filters>
<
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>
</
routing>
</
system.serviceModel>

now you can access your services via the router service like that:

private IService1 GetService()
{
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://localhost:8689/router.svc/service1");
IService1 proxy = ChannelFactory<IService1>.CreateChannel(binding, address);
return proxy;
}
Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

2 comments

  1. ToratordDrale28 בפברואר 2011 ב 2:46

    cocolovesHP|thank you for the clarification…but may i ask what that had to do with this vid?п»ї
    http://canadian-healths.com/?p=338

    thplousaqq

    Reply