Share via


How to: Route SOAP Messages Based Upon Their Content

The WSE supports routing decisions based on the content of a request message, either on content contained in the headers or on information to be found in the message body. Content-based routing enables a new path to be set by a router for a forwarded request message. This sort of service could be used, for example, to route requests to local services based on geographical data contained in the message.

Note

Users who want to process a mustUnderstand header should use a custom input filter and not content-based routing. The mustUnderstand header fault checking is done before the ProcessRequestMessage method is called, so attempting to use content-based routing always results in a mustUnderstand header fault at the client. For information on adding custom filters, see Creating Custom Filters with WSE.

The following procedures describe how to set up a router that serves as an intermediary between the clients and the server of a Web service that checks whether a message is from a client belonging to a set of clients that has signed up for a premium service or not, and then routes the client, accordingly, to either the premium or the standard service. This is a two-step process:

  1. Create and configure a WSE router.
  2. Provide the WSE router with the logic for content-based routing.

To create and configure a WSE router

  1. In Visual Studio .NET 2003, create an ASP.NET Web Service project.

    1. Start Visual Studio .NET 2003.
    2. On the File menu, point to New, and then click Project.
    3. In the Project Types pane, select Visual C# Projects.
    4. In the Templates pane, select ASP.NET Web Service.
    5. In the Location box, enter the name of the Web server with a project name of https://localhost/CBRouter.
    6. Click OK.
      The CBRouter project is added to the solution. The Component Designer appears in the development environment.
    7. In Solution Explorer, right-click CBRouter, choose Add, and then click AddClass.
    8. Under Web Project Items, select the class template, in the Name box, enter CBRoutingHandler, and then click OK.
  2. Add references to the Microsoft.Web.Services2 and System.Web.Services assemblies.

    1. In Solution Explorer, right-click References, and then select Add Reference.
    2. Click the .NET tab, select Microsoft.Web.Services2.dll, and then click Select.
    3. On the .NET tab, select System.Web.Services.dll, and then click Select.
    4. Click OK.
  3. Add Imports or using directives for WSE-related namespaces.

    1. Open the CBRoutingHandler.cs file.

    2. At the top of the file, add the directives as shown in the following code example.

      Imports System.Configuration
      Imports System.Xml
      Imports Microsoft.Web.Services2
      Imports Microsoft.Web.Services2.Messaging
      
      using System.Configuration;
      using System.Xml;
      using Microsoft.Web.Services2;
      using Microsoft.Web.Services2.Messaging;
      
  4. Edit the RoutingHandler class to derive from the Microsoft.Web.Services2.Messaging.SoapHttpRouter class**.** The edited code for the class should then read as shown in the following code example.

    Public Class RoutingHandler
        Inherits Microsoft.Web.Services2.Messaging.SoapHttpRouter
    
    public class RoutingHandler :
        Microsoft.Web.Services2.Messaging.SoapHttpRouter
    
  5. Edit the Web.config file of the WSE router to run for a Web application.

    1. In Solution Explorer, double-click Web.config.

    2. Include an <add> element for the <httpHandlers> section to specify the routing class.
      The following code example configures the WSE router to run for all SOAP requests received for files with an .asmx extension in this Web application.

      <configuration>
          <system.web>
              <httpHandlers>
                  <add verb="*" path="*.asmx"                type="CBRouter.CBRoutingHandler, CBRouter" />
              </httpHandlers>
          </system.web>
      </configuration>
      

      Note

      The type attribute of the <add> Element for <httpHandlers> (WSE for Microsoft .NET) section must be on one line, even though this example code contains line breaks for readability.

To provide content-based routing logic for the WSE router

  1. Add logic to the router that sends requests to the premium service if a client has subscribed; otherwise, send requests to the standard service.

    1. Create a method that overrides the ProcessRequestMessage method.

                        Protected Overrides Function ProcessRequestMessage(message As _
                                  SoapEnvelope) As Uri
      End Sub 'ProcessRequestMessage
      
      protected override Uri ProcessRequestMessage(SoapEnvelope message)
      
    2. Provide the logic for the content-based routing to the premium service.
      For example, if the premium clients put a header named Premium in the message to indicate that they subscribe to the premium service at PremiumServiceUri or a header named Standard in the message to indicate that they subscribe to the standard service at StandardServiceUri, the following code example could be used to insert a new via statement in the path of the forwarded message.

      ' Look for any Premium headers.
      Dim headersMatched As XmlNodeList = _
        message.Header.GetElementsByTagName(PremiumHeaderName, _
        PremiumNamespaceUri)
      If headersMatched.Count = 0 Then
          ' Defer to the WSE RoutingHandler's implementation.
          Return MyBase.ProcessRequestMessage(message)
      Else
          ' Add a new via and send it off to the premium service
          ' by adding the new via in front.
          Return premiumServiceUri
      End If
      
      // Look for any Premium headers
      XmlNodeList headersMatched =
        message.Header.GetElementsByTagName(PremiumHeaderName,
        PremiumNamespaceUri);
      if (headersMatched.Count == 0)
      {
          // Defer to the WSE RoutingHandler's implementation.
          return base.ProcessRequestMessage(message);
      }
      else
      {
          // Add a new via and send it off to the premium service
          // by adding the new via in front.
          return premiumServiceUri;
      }
      

Example

The following code example is a SOAP router that routes messages based on the SOAP headers present in the message.

Imports System
Imports System.Configuration
Imports System.Xml
Imports Microsoft.Web.Services2
Imports Microsoft.Web.Services2.Messaging

Namespace QuoteRouter
    Public Class RoutingHandler
        Inherits Microsoft.Web.Services2.Messaging.SoapHttpRouter
        Private Shared PremiumNamespaceUri As String = _
            "http://schemas.contoso.com/cbr"
        Private Shared PremiumHeaderName As String = "Premium"

        ' The uri to which this routing handler will forward premium
        ' requests to in lieu of using the default WSE RoutingHandler's
        ' implementation.
        Private premiumServiceUri As Uri

        ' Default constructor for this class.
        Public Sub New()
            ' Look up the premium web service's uri from the configuration
            ' file.
            '
            Dim premiumServiceUrl As String = _
                ConfigurationSettings.AppSettings("Premium Web Service")
            If premiumServiceUrl Is Nothing OrElse premiumServiceUrl.Length = 0 Then
                Throw New ConfigurationException("There was no ""Premium Web Service"" entry in the <appSettings> section of the router's configuration file.")
            End If

            Me.premiumServiceUri = New Uri(premiumServiceUrl)
        End Sub 'New

        Protected Overrides Function ProcessRequestMessage(ByVal message _
            As SoapEnvelope) As Uri

            ' Look for any Premium headers
            Dim headersMatched As XmlNodeList = _
                message.Header.GetElementsByTagName(PremiumHeaderName, _
                PremiumNamespaceUri)
            If headersMatched.Count = 0 Then
                ' Defer to the WSE RoutingHandler's implementation
                Return MyBase.ProcessRequestMessage(message)
            Else
                ' Add a new via and send it off to the premium service by 
                ' adding the new via in front.
                Return premiumServiceUri
            End If
        End Function 'ProcessRequestMessage
    End Class 'RoutingHandler
End Namespace 'QuoteRouter
using System;
using System.Configuration;
using System.Xml;
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Messaging;

namespace QuoteRouter
{
    public class RoutingHandler :
        Microsoft.Web.Services2.Messaging.SoapHttpRouter
    {
        static readonly string PremiumNamespaceUri = 
           "http://schemas.contoso.com/cbr";
        static readonly string PremiumHeaderName = "Premium";

        // The uri to which this routing handler will forward premium 
        // requests to in lieu of using the default WSE RoutingHandler's
        // implementation.
        Uri premiumServiceUri;

        public RoutingHandler()
        {
            // Look up the premium web service's uri from the
            // configuration file.
            string premiumServiceUrl =
                ConfigurationSettings.AppSettings["Premium Web Service"];
            if (premiumServiceUrl == null || premiumServiceUrl.Length == 0)
            {
                throw new ConfigurationException("There was no \"Premium Web Service\" entry in the <appSettings> section of the router's configuration file.");
            }

            this.premiumServiceUri = new Uri(premiumServiceUrl);
        }

        protected override Uri ProcessRequestMessage(SoapEnvelope message)
        {
            // Look for any Premium headers.
            XmlNodeList headersMatched = message.Header.GetElementsByTagName(PremiumHeaderName, PremiumNamespaceUri);
            if (headersMatched.Count == 0)
            {
                // Defer to the WSE RoutingHandler's implementation
                return base.ProcessRequestMessage(message);
            }
            else
            {
                // Add a new via and send it off to the premium service by
                // adding the new via in front.
                return premiumServiceUri;
            }
        }
    }
}

See Also

Other Resources

Routing SOAP Messages with WSE