How to Redirect WCF SOAP Services using WCF Routing Service

09. June 2015 Tutorial, WCF 0

There are scenarios where you want to forward calls to a service to another service based on its contents, the action invoked, the address, or etc.

For more info on WCF Routing Service you can refer to the following links:

https://msdn.microsoft.com/en-us/library/ee517423(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/ee517422(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/ee517424(v=vs.110).aspx

This example demonstrates how you can forward all calls coming to, let’s say Service1, to Service2. In this scenario the Service1 will be router which forwards all requests to Service2.

Download the source code

Defining the Service Contract

Create a C# Class Library. Add the following interface to the project:

namespace Common
{
    [ServiceContract]
    public interface ISampleService
    {
        [OperationContract]
        string SampleOperation();
    }
}

The interface contains a simple operation where clients will use.

Defining a Sample Service

Create another C# Class Library and add the following class which is the service implementation of ISampleService.

namespace Service2
{
    public class SampleService : ISampleService
    {
        public string SampleOperation()
        {
            return "Message from service 2";
        }
    }
}

The implementation of SampleOperation is returning a simple string message.

Host the Sample Service

Create an empty Web Application in order to host the Sample Service. Add the following references.

  • Common
  • Service2
  • System.ServiceModel

Modify the web.config and add the following section:

<system.serviceModel>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true">
    <serviceActivations>
      <add factory="System.ServiceModel.Activation.ServiceHostFactory" relativeAddress="./Sample2Service.svc" service="Service2.SampleService" />
    </serviceActivations>
  </serviceHostingEnvironment>
  <services>
    <service name="Service2.SampleService" behaviorConfiguration="DefaultServiceBehavior">
      <endpoint name="basicHttpFlightService" address="" binding="basicHttpBinding" contract="Common.ISampleService" />
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="DefaultServiceBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <extensions>
    <behaviorExtensions></behaviorExtensions>
  </extensions>
  <bindings></bindings>
</system.serviceModel>

This configuration is defining the service endpoint to be used by a client application.

Testing the Sample Service Host

Run the web application and browse the service address in the browser.

Open wcftestclient.exe add the service address.

You can see by invoking the SampleService operation we have got the expected message.

Defining Routing Service Host

Create a new empty Web Application. This web application will be the Routing Service Host. The only thing you need to do is to modify the web.config and add the Routing Configurations.

Add the following configuration to host the Routing Service:

<system.serviceModel>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true">
    <serviceActivations>
      <add factory="System.ServiceModel.Activation.ServiceHostFactory" relativeAddress="./Sample1Service.svc" 
            service="System.ServiceModel.Routing.RoutingService,System.ServiceModel.Routing, version=4.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" />
    </serviceActivations>
  </serviceHostingEnvironment>
  <services>
    <service name="System.ServiceModel.Routing.RoutingService" behaviorConfiguration="DefaultServiceBehavior">
      <endpoint name="basicHttpSampleService" address="" binding="basicHttpBinding" contract="System.ServiceModel.Routing.IRequestReplyRouter" />
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
  </services>
</system.serviceModel>

Take note that the service attribute under serviceActiovation node is used to host System.ServiceModel.Routing.RoutingService and is fully qualified it. The service endpoint and service endpoint contract are System.ServiceModel.Routing.RoutingService and System.ServiceModel.Routing.IRequestReplyRouter respectively.

Next step is to add the Routing Service Behavior and Routing Filters Configuration. Add the following section under the system.serviceModel section of configuration:

<behaviors>
  <serviceBehaviors>
    <behavior name="DefaultServiceBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <routing filterTableName="routingFilterTable" routeOnHeadersOnly="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<routing>
  <filters>
    <filter name="AddressFilter" filterType="MatchAll"/>
  </filters>
  <filterTables>
    <filterTable name="routingFilterTable">
      <add filterName="AddressFilter" endpointName="basicHttpSampleServiceClient"/>
    </filterTable>
  </filterTables>
</routing>

In the behaviors section make sure you set the httpGetEnabled attribute to true under serviceMetadata. The routing section defines the routing filter collection name.

The routing section is defining the Message Filters. The messages will be forwarded to another service based on the filters defines here.

Read more about Message Filters: https://msdn.microsoft.com/en-us/library/ee517424(v=vs.110).aspx

In this sample the MatchAll filter type is used which match all the messages.

The endpointName
basicHttpSampleServiceClient refers the client endpoint configuration where this routing service will forward messages to:

<bindings>
  <basicHttpBinding>
    <binding name="basicHttpSampleServiceBehaviour" />
  </basicHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost:51629/Sample2Service.svc"
    binding="basicHttpBinding" bindingConfiguration="basicHttpSampleServiceBehaviour"
    contract="*" name="basicHttpSampleServiceClient" />
</client>

Testing the Routing Service Host

Run the Routing Service web application and browse the service address in the browser.

Notice the service of type IRequestReplyRouter.

Sample Client Application

Create a new C# Console Application to test the Routing Service and add the following references:

  • Common
  • System.ServiceModel

Add the following section to the App.config:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpSampleService" />
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:51627/Sample1Service.svc"
            binding="basicHttpBinding" bindingConfiguration="basicHttpSampleService"
            contract="Common.ISampleService" name="basicHttpSampleService" />
    </client>
</system.serviceModel>

Take note that the endpoint contract is Common.ISampleService.

Modify the Program.cs as below:

namespace SampleServiceConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            var proxy = new ChannelFactory<ISampleService>("basicHttpSampleService").CreateChannel();

            Console.WriteLine(proxy.SampleOperation());
            Console.ReadKey();
        }
    }
}

Take note of the type ChannelFactory is initiated with, is of ISampleService, as opposed to the type the Routing Service is actually created on, which was IRequestReplyRouter.

Run the sample console application:

You can see the call to the Routing Service forwarded to the Service2.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.