Intermediary Router

Download sample

This sample demonstrates how to implement a service that provides basic routing functionality useful in network configurations where services may not be directly accessible by clients. The sample is not an example of an efficient, scalable router with a multitude of features.

Note

The setup procedure and build instructions for this sample are located at the end of this topic.

In a typical communication scenario that involves SOAP intermediaries, a message sent by a client traverses one or more additional services before reaching its final destination—the service that actually processes the message and provides a response, if one is expected. A SOAP intermediary performs various actions on the message that is passing through it. For example, a caching intermediary would return a cached response to the message, which alleviates stress on the service that would have to process the request again. A load-balancing intermediary would use a round-robin algorithm to forward the message to one of many potential services. A schema validation intermediary would only forward messages that are fully compliant with the XSD of the contract and, possibly, other protocols. The intermediary developed for this sample is responsible for routing messages to an appropriate service based on the message's headers and content.

For more information about SOAP messages, see XML Web Service Wire Formats.

In this sample, two application services are deployed to process client requests—a calculator service and an echo service. The services' application endpoints are only accessible from the internal network. The service's metadata exchange (MEX) endpoints are accessible publicly. The SOAP router is part of the internal network and all application requests coming from outside the internal network must pass through it.

The client was created by running the Service Model Metadata Utility Tool (Svcutil.exe) against both services, to generate two code files (one client for each service) and one configuration file as Svcutil.exe merges the configuration information from the second service into the existing configuration file created when Svcutil.exe was run against the first service. The Web Services Description Language (WSDL) provided by each service contains the address of the SOAP intermediary instead of the address of the actual service. This frees the client from modifying the configuration file or knowing what the address of the SOAP intermediary is.

Furthermore, the router service in this sample is configured with two endpoints—one listening for text-encoded messages using HTTP for SOAP 1.2, and the other listening for binary encoded messages using TCP for SOAP 1.2. Each application service's WSDL uses the right endpoint address on the router. The router is also provided with routing information in the appSettings section of the configuration file that contains the following properties:

  • prefixes and namespaces - used to update the default XmlNamespaceManager in WCF so it can resolve prefixes located in the router's XPaths.

  • xpath and epr - used to add routing entries to the routing table that maps XPaths to EPRs.

The router uses the XpathMessageFilterTable (XPathFilterTable<T>) class, where "T" is a EndpointAddress that stores the routing entries the user provides. When a message is received, the router calls the MatchMultiple method passing in a Message instance and retrieves an EndpointAddress to which it forwards the message.

Both the EchoService and the CalculatorService use the ListenUri property to set the URI that the endpoint is listening on. The address provided inside the endpoint declaration is the address of the router's endpoint that is capable of forwarding the service's messages. This is the address that appears in the service's WSDL and the address that matches against the WS-Addressing To header of every incoming message. However, the address provided by the ListenUri property is the endpoint's actual physical listening address that is used only by the transport.

WCF provides another behavior that is typically used in SOAP intermediary scenarios that this sample does not exercise—the ClientViaBehavior channel behavior. The ClientViaBehavior is used by clients to specify the URI for which the transport channel should be created. If such a behavior exists in the behavior collection on a client endpoint, the transport uses the URI that it provides, while all the other channel layers in the stack use the EndpointAddress provided at ChannelFactory construction time. This EndpointAddress also becomes the WS-Addressing To header. The following sample code shows how this behavior is used.

ChannelFactory<IContract> factory = new ChannelFactory<IContract>(new EndpointAddress("http://hostname/service"));
factory.Endpoint.Behaviors.Add(new ClientViaBehavior(new Uri("http://hostname/intermediary")));
IContract channel = factory.CreateChannel(); 

Another WCF feature that is used with SOAP intermediaries is the AddressFilter property. The AddressFilter is used by WCF to accept only messages that match a particular filter. If the service contract's methods use "*" as the Action, only the address is checked. This sample does not make use of this feature because the address is always correct. The router accepts the client's messages because the To headers match its endpoint address, and the services accept messages that are forwarded to them because their To header matches their endpoint's logical address.

The sample's Contracts.cs file defines the following four interfaces, one for each transport pattern:

  • ISimplexDatagramRouter. This interface is required to accept messages on simplex datagram channels. Add an endpoint using this interface if you expect messages on one-way HTTP channels, or one-way TCP and NamedPipe channels.

  • IRequestReplyDatagramRouter. This interface is required to accept messages on request-reply datagram channels. Use this interface for messages on a two-way HTTP channel.

  • ISimplexSessionRouter. This interface must accept messages on simplex sessionful channels. Use this interface for simplex TCP and simplex NamedPipe channels.

  • IDuplexSessionRouter. This interface is for duplex session channels. Use this interface for duplex TCP and duplex NamedPipe channels.

The RouterBinding provides an example of a WCF binding you can create to support your SOAP intermediary. It allows you to specify the most common settings required in this scenario and ensures only those binding elements that are truly required get added. Basic configuration support is demonstrated, as well.

This sample does not use Web hosting because it relies on transports other than HTTP. TCP activation is currently only available on Windows Vista and IIS 7.0.

When you run the sample, the operation requests and responses are displayed in the client console window. Press ENTER in the client window to shut down the client.

Echo("Is anyone there?") returned: Is anyone there?
Add(5) returned: 5
Add(-3) returned: 2

To set up, build, and run the sample

  1. To build the C#, C++, or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  2. To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples with the following exceptions.

    1. In both the single-machine and cross-machine configurations, four projects and four executables are required—one for the client, one for the SOAP router, and one for each application service.

    2. In a cross-machine configuration, the following changes must be made to the four configuration files.

      The App.config file for the CalculatorService and EchoService must be changed on line 21. The intermediary's real hostname must replace the localhost hostname.

      The Router's App.config file must be changed on line 15. The two addresses (separated with a '|') must be changed to the hostname of the EchoService and CalculatorService, respectively.

      The Client's App.config file must be changed on lines 5 and 7. The intermediary's real hostname must replace the localhost hostname.

      You can also use the Service Model Metadata Utility Tool (Svcutil.exe) against the two application services (once they are updated to use the right address) and regenerate the App.config files.

  3. Ensure that the Router, EchoService, and CalculatorService are all running before you start the client. Each of the three services print out the endpoint addresses on which they are listening at startup.

    Note

    The EchoService's and CalculatorService's application endpoint uses the router's address.

  4. Run the client. The client first contacts the EchoService, and then the CalculatorService. The Router prints out the WS-Addressing actions of messages it is forwarding, in both directions.

    Note

    If Client.exe and Router.exe are on separate machines, uncomment the <identity/> section in Client.exe.config and set the user principal name to the one of the user running Router.exe.

© 2007 Microsoft Corporation. All rights reserved.