Exercise 9: Content Based Routing
In the previous exercise, you routed all requests bound for your service bridging the protocol from HTTP to TCP. However, there are many cases where you want to route requests based on the content of the message. While you can route based on content from the message body for performance it is recommended that you route based on content in the message headers.
In this exercise, you will add a variation of the calculator service that uses rounding. You will then route to this service messages that contain a special header while other messages that do not have the header will use the regular calculator service.
Figure 33
The routing service routing based on message header content
Task 0 – Opening the Solution
This exercise uses a new begin solution which contains a new service, the RoundingCalculatorService project and some updates to the CalculatorClient application.
- Open the starting solution for Exercise 9 located under the Source\Ex9-ContentRouting\Begin(choosing the folder that matches the language of your preference.) Use it as the starting point for this exercise.
- Press CTRL+SHIFT+B to build the solution.
The CalculatorClient application now has a button on the toolbar to indicate if you want to use the Rounding calculator. Even though this is a different service, you will send the message to the same routing service. In this task, you will write the code to add a custom header that the router will use to route the message.
- In the CalculatorClient project open MainWindow.xaml.cs (C#) or MainWindow.xaml.vb (Visual Basic).
Locate the AddOptionalRoundingHeader method and modify it as shown to add a custom header to outgoing messages that will use the RoundingCalculator.
(Code Snippet - What is new in WCF4 Lab –AddOptionalRoundingHeader method CSharp)
private void AddOptionalRoundingHeader(
FakePre-98e437d3e7e84989ab5291777f5e037c-49e57c63caea4b67b527a3eb182213a0FakePre-ec3703ec6a3641868d123cdc58bed9de-c04357e9bb5548afaae28326ac9950ef if (this.checkRounding.IsChecked.Value == true) { OperationContext ctx = OperationContext.Current; MessageHeaders messageHeadersElement = ctx.OutgoingMessageHeaders; ctx.OutgoingMessageHeaders.Add( MessageHeader.CreateHeader( "RoundingCalculator", "https://my.custom.namespace/", "1")); }FakePre-c54ae6b2fb14433185174614fc353338-a3ca7b110ab845569c450635dba6afa4
(Code Snippet - What is new in WCF4 Lab –AddOptionalRoundingHeader method VB)
Private Sub AddOptionalRoundingHeader(ByVal proxy As CalculatorServiceClient)
If (Me.checkRounding.IsChecked.Value = True) Then Dim ctx = OperationContext.Current Dim messageHeadersElement = ctx.OutgoingMessageHeaders ctx.OutgoingMessageHeaders.Add( MessageHeader.CreateHeader( "RoundingCalculator", "https://my.custom.namespace/", "1")) End IfFakePre-e45a3b9e0dd543cea07bc669878f4201-c0ef8148447344ce8891256fbe14b3e0
Task 2 – Adding a New Entry to the Filter Table
In this task, you will modify the router to detect this new header and route the message to the rounding calculator.
Because your header uses a custom namespace, you will need to create a namespace table. In the RouterService project open the Web.config file and add the following configuration to the routing section.
(Code Snippet - What is new in WCF4 Lab –Namespace Table XML)
<routing>
<namespaceTable> <add prefix="custom" namespace="https://my.custom.namespace/"/> </namespaceTable>
Now you can define a new kind of filter that will match using an XPath expression. Add the following filter definition to the Web.config file. This filter will match on messages with the custom RoundingCalculatorHeader with a value of 1.
(Code Snippet - What is new in WCF4 Lab –XPathFilter XML)
<filters>
<filter name="XPathFilter" filterType="XPath" filterData="sm:header()/custom:RoundingCalculator = 1"/>
You need to add a new endpoint address for the RoundingCalculatorService so that you can route to it. Modify the Web.config file in the RouterService project, and add the new endpoint definition to the client section as shown.
(Code Snippet - What is new in WCF4 Lab – roundingCalculatorEndpoint XML)
<client>
<endpoint name="roundingCalculatorEndpoint" address="net.tcp://localhost:8080/RoundingCalculatorService" binding="netTcpBinding" bindingConfiguration="CalculatorService" contract="*" />
Finally, you need to add the new filter to the filter table. The filter table evaluates matches based on the order of priority in the filters with higher numbers having higher priority. Because you want the XPathFilter to match messages before the MatchAll filter you need to give it a higher priority. Open the Web.config of the RouterService, and modify the filterTable configuration as shown.
(Code Snippet - What is new in WCF4 Lab – filterTable1 XPathFilter XML)
<filterTable name="filterTable1">
<add filterName="XPathFilter" endpointName="roundingCalculatorEndpoint" priority="1"/>FakePre-9640a03118c942fe8630719f998a37a0-127ddbd0699949dda46c36566a6839ffFakePre-5bdadae3f00e4f4b87b766ceda55fa59-9e2c1ec249f04d7b83014f47327d8003FakePre-84bcf8bcdea4409aba7f412244a4a092-0cf11798c64b4cf9a26e57844ef7a4daFakePre-6c0fa83b474c4fe69951db05f7649716-8cd9e8c9db6447ccbd57517c2eb7b14d
Next Step
Exercise 9: Verification