Routing in WCF - Action Filters

In my previous article, we discussed about the basic concept of routing in WCF service. We learned about how we can configure the router service and add filters to it. Now let's try to apply this in a practical example.
 
So we will start by creating an empty solution and add following projects in it:
  1. Two wcf services, Service_1 and Service_2. These two services will have simple methods GetData1 and GetData2 respectively which will simply return the string with data entered by the user.

  2. Another wcf service which will act as the routing service. 

  3. A windows application which will call the router service, which will further forward the call to either Service_1 or Service_2. 
So our complete solution will look like the following:
 
 
So we will start by adding the GetData methods in our services Service_1 and Service_2. So these will look like the following: 
  1.    public class Service1 : IService1  
  2.    {  
  3.        public string GetData(int value)  
  4.        {  
  5.            return string.Format("Data retuned from Service 1: {0}", value);  
  6.        }  
  7.    }  
  8.   
  9.    public class Service2 : IService2  
  10.    {  
  11.        public String GetData(Int32 value)  
  12.        {  
  13.            return string.Format("Data retuned from Service 2: {0}", value);  
  14.        }  
  15.    }   
Next, we will configure our router service with the settings as per our previous discussion here. So, we will start by creating the basic configuration for the service, like defining the endpoint address, contract and service behavior of our routing service. So it would look like the following: 
  1. <services>  
  2.      <service name="System.ServiceModel.Routing.RoutingService"  
  3.                  behaviorConfiguration="RoutingSvcBehavior">  
  4.        <endpoint  
  5.                  address=""  
  6.                   binding="wsHttpBinding"   
  7.                   contract="System.ServiceModel.Routing.IRequestReplyRouter"/>  
  8.      </service>  
  9.    </services>  
  10.   
  11.    <behaviors>  
  12.      <serviceBehaviors>  
  13.        <behavior name="RoutingSvcBehavior">  
  14.          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>  
  15.          <serviceDebug includeExceptionDetailInFaults="true"/> 
  16.          <routing filterTableName="ServiceRouterTable"/> 
  17.        </behavior>  
  18.      </serviceBehaviors>  
  19.    </behaviors>  

Next we define the possible endpoints, where the request can get routed to. So this section will look like the following:
  1. <client>  
  2.      <endpoint  
  3.              name="Service_1" binding="wsHttpBinding"  
  4.               address="http://localhost:65145/Service1.svc"  
  5.               contract="*">  
  6.      </endpoint>  
  7.      <endpoint  
  8.              name="Service_2" binding="wsHttpBinding"  
  9.               address="http://localhost:65253/Service2.svc"  
  10.               contract="*">  
  11.      </endpoint>  
  12.   
  13.    </client>  
Moving on, we will define our filters which will use the filterType as Action. Based on the action request, it will route to either Service_1 or Service_2.
So our filter section will look like the following: 
  1. <routing>  
  2.     <filters>  
  3.       <filter name="MyFilter"  filterType="Action" filterData="http://tempuri.org/IService1/GetData"/>  
  4.       <filter name="MyFilter2" filterType="Action" filterData="http://tempuri.org/IService2/GetData"/>  
  5.     </filters>  
  6.     <filterTables>  
  7.       <filterTable name="ServiceRouterTable">  
  8.         <add filterName="MyFilter" endpointName="Service_1"/>  
  9.         <add filterName="MyFilter2" endpointName="Service_2"/>  
  10.       </filterTable>  
  11.     </filterTables>  
  12.   </routing>  
Next, we will configure the Program.cs of our router service to host the application. So the Main function will look like the following: 
  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             ServiceHost Host = new ServiceHost(typeof(RoutingService));  
  6.             try  
  7.             {  
  8.                 Host.Open();  
  9.                 Console.WriteLine("Routing Service is Started...............");  
  10.                 Console.ReadLine();  
  11.                 Host.Close();  
  12.   
  13.             }  
  14.             catch (Exception ex)  
  15.             {  
  16.                 Console.WriteLine(ex.Message);  
  17.             }  
  18.             Console.ReadLine();  
  19.         }  
  20.     }  
Now, is the time to call the router service from our windows application. To start with, we will add a textbox and two buttons which will call the router service. So our form will look like the following:
 
Next, we will add service references to the Service_1 and Service_2, to this project in order to call these services. Once we add these references, the system will generate its configuration code in the App.config. We will remove all the generated configuration and add the following client end points. These will simply redirect the user to the router service, instead of directly routing them to Service_1 or Service_2.
  1. <system.serviceModel>  
  2.      
  3.    <bindings>  
  4.      <wsHttpBinding>  
  5.        <binding name="WSHttpBinding_IService2" />  
  6.      </wsHttpBinding>  
  7.    </bindings>  
  8.    <client>  
  9.      <endpoint address="http://localhost:5643/MyServ" binding="wsHttpBinding"  
  10.        contract="ServiceReference1.IService1" name="routingSvcEndPoint_Svc1" />  
  11.      <endpoint address="http://localhost:5643/MyServ" binding="wsHttpBinding"  
  12.        contract="ServiceReference2.IService2" name="routingSvcEndPoint_Svc2" />  
  13.    </client>  
  14.  </system.serviceModel>  
On click of these buttons, we will add the following code, which will call the Service_1 or Service_2. Note that we could have also used the ChannelProxy to call the services. But in that case, it would have required us to use common Interface contract among the services and the client applications. So our code will look like the following:
  1. private void button1_Click(object sender, EventArgs e)  
  2. {  
  3.     ServiceReference1.Service1Client _client = new ServiceReference1.Service1Client("routingSvcEndPoint_Svc1");  
  4.     label2.Text = "Response from Service 1: " + _client.GetData(Convert.ToInt32(textBox1.Text));  
  5. }  
  6.   
  7. private void button2_Click(object sender, EventArgs e)  
  8. {  
  9.     ServiceReference2.Service2Client _client2 = new ServiceReference2.Service2Client("routingSvcEndPoint_Svc2");  
  10.     label2.Text = "Response from Service 2: " + _client2.GetData(Convert.ToInt32(textBox1.Text));  
  11. }  
Finally we will set multiple projects as start-up projects.

 
Run the application, enter the values and see the results.

How it works ?

When we call the service1 or service2, using client proxies, we get the endpoint routingSvcEndPoint_Svc1 or routingSvcEndPoint_Svc2. These will route the requests to the router service. Router service will check its filter configuration and based on the action defined in filterData, it will select either MyFilter or MyFilter2. It will pick the corresponding endpoint from filterTable and route the request to its service.

Hope you enjoyed reading it. Complete source code is also attached here. Happy coding...!!! 
 
Read more articles on WCF


Similar Articles