Building the Content Based Routing Solution on Microsoft Platform

Richard Seroter

September 2010

The flow of the solution looks like the following:

Building the Content Based Routing Solution on Microsoft Platform

An order comes from a customer to a single endpoint at McKeever Technologies. This single endpoint then routes the order based on the content of the order (that is, the value of the Product ID element). The router sends requests to WCF Workflow Services, which can provide us durability and persistence when talking to the backend order management systems. If an order system is down, then the workflow gets suspended and will be capable of resuming once the system comes back online.


First, create a new database named Chapter8Db in your local SQL Server 2008 instance. Then locate the database script named Chapter8Db.sql in the folder <Installation Directory>\Chapter8\Begin and install the tables into your new database. When completed, your configuration should look like the following screenshot:

Building the Content Based Routing Solution on Microsoft Platform

Next, open Chapter8.sln in the <Installation Directory>\Chapter8\Begin folder. In this base solution you will find two WCF services that represent the interfaces in front of the two order management systems at McKeever Technologies. Build the services and then add both of them as applications in IIS. Make sure you select the .NET 4.0 application pool.

Building the Content Based Routing Solution on Microsoft Platform

If you choose, you can test these services using the WCF Test Client application that comes with the .NET 4.0 framework. If your service is configured correctly, an invocation of the service should result in a new record in the corresponding SQL Server database table.

Building the workflow

Now that our base infrastructure is in place, we can construct the workflows that will execute these order system services.

  1. Launch Visual Studio.NET 2010 and open Chapter8.sln in the &ltInstallation Directory>\Chapter8\Begin folder. You should see two WCF services.

    Building the Content Based Routing Solution on Microsoft Platform

  2. We now must add a new workflow project to the solution. Recall that this workflow will sit in front of our order service and give us a stronger quality of service, thanks to the persistence capability of AppFabric. In Visual Studio .NET 2010, go to File and select New Project.
  3. Select the WCF Workflow Service project type under the Workflow category and add the project named Chapter8.SystemA.WorkflowService to our existing solution.

    Building the Content Based Routing Solution on Microsoft Platform

  4. This project is now part of the solution and has a default workflow named Service1.xamlx.

    Building the Content Based Routing Solution on Microsoft Platform

  5. Rename the Service1.xamlx file to SystemAOrderService.xamlx from within the Solution Explorer. Also click the whitespace within the workflow to change both the ConfigurationName and Name properties.

    Building the Content Based Routing Solution on Microsoft Platform

  6. We want all our service-fronting workflows to have the same external-facing contract interface so that we can effectively abstract the underlying service contracts or implementation nuances. Hence, we add a new class file named OrderDataContract.cs to this workflow project. This class will hold the data contracts defining the input and output for all workflows that sit in front of order systems.
  7. Make sure the project itself has a reference to System.Runtime.Serialization, and then add a using statement for System.Runtime.Serialization to the top of the OrderDataContract.cs class. Add the following code to the class:

    namespace Chapter8.WorkflowService
    Namespace = "http://Chapter8/OrderManagement/DataContract")]
    public class NewOrderRequest
    public string OrderId { get; set; }
    public string ProductId { get; set; }
    public string CustomerId { get; set; }
    public int Quantity { get; set; }
    public DateTime DateOrdered { get; set; }
    public string ContractId { get; set; }
    public string Status { get; set; }
    Namespace = "http://Chapter8/OrderManagement/DataContract")]
    public class OrderAckResponse
    public string OrderId { get; set; }

  8. Open the SystemAOrderService.xamlx workflow, click on the top ReceiveRequest shape, and set the following property values. Note that we will use the same values for all workflows so that the external-facing contract of each workflow appears the same.

    Property Value
    DisplayName ReceiveOrderRequest
    OperationName SubmitOrder
    ServiceContractName {http://Chapter8/OrderManagement} ServiceContract
    Action http://Chapter8/OrderManagement/SubmitOrder
    CanCreateInstance True

  9. Click the Variables tab at the bottom of the workflow designer to show the default variables added to the workflow.

    Building the Content Based Routing Solution on Microsoft Platform

  10. Delete the data variable.
  11. Create a new variable named OrderReq. For the variable type, choose Browse for Types and choose the NewOrderRequest type we defined earlier in the OrderDataContract.cs class.

    Building the Content Based Routing Solution on Microsoft Platform

  12. Add another variable named OrderResp and choose the previously defined OrderAckResponse .NET type.
  13. The OrderReq variable gets instantiated by the initial request, but we need to explicitly set the OrderResp variable. In the Default column within the Variables window, set the value to New OrderAckResponse().
  14. Set a proper variable for the initial receive shape by clicking on the ReceiveOrderRequest shape and click on the View Message link. Choose OrderReq as the Message data and set the type as NewOrderRequest.

    Building the Content Based Routing Solution on Microsoft Platform

  15. Now we do the same for the response shape. Select the SendResponse shape and click on the View Message link. Choose the OrderResp variable as the Message data and OrderAckResponse as the Message type.
  16. Keep the SendResponse shape selected and set its PersistBeforeSend property to On. This forces a persistence point into our workflow and ensures that any errors that occur later in the workflow will lead to a suspended/resumable instance.
  17. We can test our workflow service prior to completing it. We want to populate our service response object, so go to the Workflow toolbox, view the Primitives tab, and drag an Assign shape in between the existing receive and send shapes.

    Building the Content Based Routing Solution on Microsoft Platform

  18. In the Assign shape, set the To value to OrderResp.OrderID and the right side of the equation to System.GUID.NewGUID().ToString(). This sets the single attribute of our response node to a unique tracking value.
  19. Build the workflow and if no errors exist, right-click the SystemAOrderSystem.xamlx workflow in the Solution Explorer and choose View in Browser.
  20. Open the WCF Test Client application and point it to our Workflow Service endpoint. Double-click the Submit Order operation, select the datatype in the Value column, and enter test input data. Click on the Invoke button and observe the response object coming back with a GUID value returned in the OrderId attribute.

    Building the Content Based Routing Solution on Microsoft Platform

  21. Now we're ready to complete our workflow by actually calling our target WCF service that adds a record to the database table. Return to Visual Studio. NET, right-click the Chapter8.SystemA.WorkflowService project, and choose Add Service Reference.
  22. Point to the service located at http://localhost/Chapter8.OrderManagement.SystemA/OrderIntakeService.svc and type SystemASvcRef as the namespace.
  23. If the reference is successfully added and the project is rebuilt, then a new custom workflow activity should be added to the workflow toolbox. This activity encapsulates everything needed to invoke our system service.

    Building the Content Based Routing Solution on Microsoft Platform

  24. Add variables to the workflow that represent the input and output of our system service. Create a variable named ServiceRequest and browse for the type Order, which can be found under the service reference. Set the default value of this variable to New Order().

    Building the Content Based Routing Solution on Microsoft Platform

  25. Create another variable named ServiceResponse and pick the same order object but do not set a default value.
  26. Drag the custom AddOrder activity from the workflow toolbox and place it after the SendResponse shape. This sits after the workflow service response is sent, so that if errors occur the caller will not be impacted.
  27. Click the AddOrder shape and set its NewOrder property to the ServiceRequest variable and its AddOrderResult property to ServiceResponse.
  28. Now we have to populate the service request object. Drag a Sequence workflow activity from the Control Flow tab and drop it immediately before the AddOrder shape.
  29. Add six Assign shapes to the Sequence and set each activity's left and right fields as follows:

    Left Side Right Side
    ServiceRequest.ContractId OrderReq.ContractId
    ServiceRequest.CustomerId OrderReq.CustomerId
    ServiceRequest.DateOrdered OrderReq.DateOrdered
    ServiceRequest.OrderNumber OrderResp.OrderId
    ServiceRequest.ProductId OrderReq.ProductId
    ServiceRequest.Quantity OrderReq.Quantity

    Note that the OrderNumber value of the request is set using the OrderResp object as that is the one to which we added the GUID value.

  30. Our final workflow should look like the following:

    Building the Content Based Routing Solution on Microsoft Platform

Read more about this book

  • Open the web.config file for the Workflow Service and add the following configuration entry within the System.ServiceModel node. This makes our Workflow Service leverage the WsHttpBinding by default and eliminates issues that arise when using the BasicHttpBinding with the WCF Routing Service.
    <add scheme="http" binding="wsHttpBinding"/>
  • Build the workflow and switch to IIS. Add a new application named Chapter8.SystemA.WorkflowService to the Default Web Site. Choose a .NET 4.0 application pool and set the path to the location of your service project.
  • Right-click the Default Web Site, choose Edit Bindings, and ensure that net.pipe is listed there.

    Building the Content Based Routing Solution on Microsoft Platform

  • Visit the Advanced Settings of the default website and make sure that net.pipe is part of the Enabled Protocols. This is needed to support the AppFabric persistence functionality.

    Building the Content Based Routing Solution on Microsoft Platform

  • Right-click the new WF service application and choose Manage WCF and WF Services and select Configure. On the Workflow Persistence tab, make sure that SQL Server Workflow Persistence is selected. On the Workflow Host Management tab, confirm that the Action on Unhandled Exception is set to Abandon and suspend.

    (Move the mouse over the image to enlarge.)

  • Now we can employ the WCF Test Client to call our workflow service and see a record show up in our database table.
  • In order to flex the true value-add of the AppFabric hosting environment, turn off the Chapter8.OrderManagement.SystemA application by right-clicking it, selecting the Manage WCF and WF Services menu item, and choosing Stop Application. This effectively simulates failure of our downstream order system making it unavailable and offline.
  • Call the workflow service again and if you view the AppFabric dashboard, you should see a Suspended message.

    Building the Content Based Routing Solution on Microsoft Platform

  • Confirm this fact by viewing your database table and noticing that no new record has been added.
  • Restart the Chapter8.OrderManagement.SystemA application to simulate our order system coming back online.
  • Click on the suspended message in the AppFabric console and choose to resume the suspended instance.

    Building the Content Based Routing Solution on Microsoft Platform

  • The instance is resumed and a new record should be added to the OrderManagement_SystemA database table.
  • Build one more workflow that is nearly identical to this first one, except that it consumes the system B order system service.
  • Create a new WCF Workflow Service application named Chapter8.SystemB.WorkflowService and add it to the existing Visual Studio.NET solution.
  • Rename the physical xamlx file to SystemBOrderService.xamlx and set both the Configuration Name and Name property of the workflow to SystemBOrderService.
  • Copy the OrderDataContract.cs file from the Chapter8.SystemA.WorkflowService project to the Chapter8.SystemB.WorkflowService project. Recall that we want all workflows of the front order systems to have the same external-facing data contract.
  • On the ReceiveRequest shape, change the name to ReceiveOrderRequest, Operation Name to SubmitOrder, ServiceContractName to {http://Chapter8/OrderManagement}ServiceContract, and Action to http://Chapter8/OrderManagement/SubmitOrder. These values are identical to our previous workflow and help us have the same external-facing contract definition for both services.
  • Add a service reference to http://localhost/Chapter8.OrderManagement.SystemB/OrderService.svc and set the namespace to SystemBSvcRef.
  • Create the variables for the workflow service request and response as well as the system B service request and response.

    Building the Content Based Routing Solution on Microsoft Platform

  • Add an Assign shape between the workflow service request and response and set the response's OrderId value equal to System.GUID.NewGUID().ToString().
  • After building the project, drag the new custom AddNewOrder workflow activity below the service response shape, set its input and output attributes to the previously defined variables, and finally set its six properties using a sequence of Assign shapes.
  • Exactly like the earlier Workflow Service, add the following configuration block to the web.config file:

    <add scheme="http" binding="wsHttpBinding"/>

  • Compile the service and create an IIS web application named Chapter8.SystemB.WorkflowService and configure it identically to the Chapter8.SystemA.WorkflowService application.
  • Test the service by calling it via the WCF test client and confirming that your data is added to the OrderManagement_SystemB database table.
  • Adding a router service

    Now we have two independent workflow services that sit in front of our order systems. We don't want our customers to know which service to call, but rather, we want them to send all their orders to one place and expect that McKeever Technologies will figure out a way to enter data accurately into appropriate systems.

    WCF 4.0 introduces a pre-built routing service that uses configuration values to direct messages to endpoints, based on a variety of criteria. We can route messages based on their content, SOAP action, custom headers, and more. There's a great amount of flexibility we can add to our solution architecture when rich capabilities like message routing are simply baked into a framework.

    The steps for building this part of the solution are as follows:

    1. In Visual Studio.NET, add a new website of type WCF Service to our existing solution and name it Chapter8.OrderManagement.RoutingService.

      Building the Content Based Routing Solution on Microsoft Platform

    2. Delete the code files (interface and service implementation). We are leveraging the native WCF 4.0 Routing Service and therefore don't need any code files.
    3. Add a project reference to System.ServiceModel.Routing.
    4. Rename the .svc file to OrderRouter.svc.
    5. Open the service file (.svc) and change its Service attribute reference to System.ServiceModel.Routing.RoutingService,System.ServiceModel.Routing, version=, Culture=neutral,PublicKeyToken=31bf3856ad364e35. This tells the WCF service to use the built-in router service for its implementation.
    6. We need to set up the web.config file to implement the routing capability. within the System.Configuration tags, add the <client> node. This holds the endpoint definition for both of our order system workflow services. Note that we don't identify the contract definition because this project technically has no idea about our service or its contract implementation.
      SystemAOrderService.xamlx" binding="wsHttpBinding"
      bindingConfiguration="" contract="*" name="OrderSystemA" />
      SystemBOrderService.xamlx" binding="wsHttpBinding"
      bindingConfiguration="" contract="*" name="OrderSystemB" />
    7. We create the new WCF 4.0 routing section. We first have a namespace table, which allows us to create an alias to the namespace of our data message. Next, we have a filters collection where we have XPath filters for each order system and which sends messages with ProductId < 100 to system A and ProductId > 100 to system B. Finally, we have a filter table, which links the filters and determines which endpoint to use when the filter is satisfied.

      <add prefix="custom"
      <filter name="SystemAFilter" filterType="XPath"
      filterData="//custom:ProductId &lt; '100'"/>
      <filter name="SystemBFilter" filterType="XPath"
      filterData="//custom:ProductId &gt; '100'"/>
      <filterTable name="filterTable1">
      <add filterName="SystemAFilter" endpointName="OrderSystemA"
      <add filterName="SystemBFilter" endpointName="OrderSystemB"

    8. We add a service and behavior entry. The behavior refers to the new routing capability, and the service points to the framework-provided routing service.

      <service behaviorConfiguration="RoutingBehavior" name="System.
      <endpoint address="" binding="wsHttpBinding"
      name="RouterEndpoint1" contract="System.ServiceModel.
      Routing.IRequestReplyRouter" />
      <behavior name="RoutingBehavior">
      <routing routeOnHeadersOnly="false"
      filterTableName="filterTable1" />
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceMetadata httpGetEnabled="true" />

    9. Build the application and create a new IIS application named Chapter8.OrderManagement.RoutingService, which runs in the .NET 4.0 application pool.
    10. We can browse directly to the service address to see if our service is online: http://localhost/Chapter8.OrderManagement.RoutingService/OrderRouter.svc.
    11. If you browse the WSDL of this service, you will notice that it has a generic request-reply message exchange pattern. Clients of this service should point to a well-defined WSDL that outlines the specific service and data contracts.
    12. To test this service, create a new console application and add a service reference to either of our previously built workflow services. Add the following code to the Main operation:

      static void Main(string[] args)
      Console.WriteLine("Starting Up Service Client ...");
      Console.WriteLine("Enter a product to order");
      string prodId = Console.ReadLine();
      OrderSvcRef.ServiceContractClient c = new
      OrderSvcRef.NewOrderRequest request = new
      request.ContractId = "001";
      request.CustomerId = "333";
      request.DateOrdered = DateTime.Now;
      request.ProductId = prodId;
      request.Quantity = 10;
      request.Status = "Submitted";
      OrderSvcRef.OrderAckResponse response = c.SubmitOrder(request);
      Console.WriteLine("Response is " + response.OrderId);

    13. Open the app.config file for the project and find the endpoint added by the service reference. Remove the URL to the specific workflow service and replace it with the generic router address. http://localhost/Chapter8.OrderManagement.RoutingService/OrderRouter.svc.
    14. Build and run the console application and if you enter a product ID below 100, you should see a record added to the SystemA database table, and conversely, if you enter a product ID greater than 100, you should find a new record in the SystemB database table.


    In this article we constructed a working version of the proposed solution, which leveraged core components of .NET 4.0 (WCF and Windows Workflow Services) as well as the AppFabric extensions to IIS.

    You've been reading an excerpt of:

    Applied Architecture Patterns on the Microsoft Platform

    Explore Title