Custom Routing


In the previous section, we looked at server-controlled routing using the RoutingHandler HTTP handler. Another server-controlled routing option we can consider is routing the message based on the content of the message or some external factor.

We can easily accomplish this by deriving a new class from RoutingHandler and using this as the handler for the Web services we want to route.

By deriving from RoutingHandler, we gain the basic routing functionality that RoutingHandler provides. ProcessRequestMessage is called by ProcessRequest and we override the ProcessRequestMessage method to perform our custom routing; whatever Path details we specify will be used by the ProcessRequest method and the message will be routed to the correct destination.

For this example, we’ll use a custom router that will route the incoming message to a different Web service, depending on the time of the day. We might use this sort of routing in a stock-trading scenario—depending on the time of day, we’d route to Tokyo, London, or New York.

Building the Custom Router

To build a custom router, we simply create a new class and set it to inherit from RoutingHandler—nothing more to it:

public class CustomRouter : Microsoft.Web.Services.Routing.RoutingHandler {      }

We now have a custom router with all the functionality of RoutingHandler. We haven’t overridden the ProcessRequestMessage and ProcessResponseMessage methods, so the custom router will have exactly the same functionality as the standard RoutingHandler class.

We’ll look at what to do within our custom router in a moment. For now, we can leave it performing the same function as RoutingHandler. We’ll first look at how to configure the server to use the custom router.

We inherited from a class that implements IHttpHandler, so we can simply use this derived class as the HTTP handler for whichever routers we require. In this case, we’ll implement RouterD.asmx, which will use the code in our CustomRouter class:

<add path="RouterD.asmx" verb="*" type="_14.CustomRouter, 14" />

We’ve simply specified the type of the class in the normal manner; whenever a request is made to RouterD.asmx, an instance of our CustomRouter class is instantiated and the ProcessRequest method is called.

That’s it! Our custom router is now configured to run on the server. If you try to connect to it, however, you’ll get a SoapHeaderException message because the router doesn’t have an entry in the referral cache—nor does it have routing details specified in the incoming message. We’ve built a custom router but we’re still using the default routing provided by RoutingHandler.

As we pointed out earlier, we’ll route the request from http://localhost/wscr/14/RouterD.asmx to a different Web service depending on the Coordinated Universal Time (UTC) time of day. Whichever Web service we route to will return its URL as well as the route that the request took to its destination. This is exactly the same as what we return from the TellMe.asmx service, which we looked at earlier.

Between midnight and 8 A.M. we’ll route to Tokyo.asmx, between 8 A.M. and 4 P.M. we’ll route to London.asmx, and between 4 P.M. and midnight we’ll route to NewYork.asmx. This scenario is shown in Figure 14-8.

click to expand
Figure 14-8: The custom routing scenario

The code to actually do the routing is really quite simple. In our example here, we’re not actually using the content of the incoming request to determine the route— we’re relying on the time of day to determine the route. We do, however, have access to the SoapEnvelope object for the incoming request, and we can interrogate this to determine the route, if required.

The code for the overridden ProcessRequestMessage is shown here:

protected override void ProcessRequestMessage(SoapEnvelope message,     Path outgoingPath) {     Via destinationService;     // get the time of day     DateTime dateNow = DateTime.Now;     // set the destination correctly     if(dateNow.Hour >=0 && dateNow.Hour <8)     {         destinationService = new Via(TokyoUri);     }     else if(dateNow.Hour >=8 && dateNow.Hour <16)     {         destinationService = new Via(LondonUri);     }     else     {         destinationService = new Via(NewYorkUri);     }     // now go to the route we've specified     outgoingPath.Fwd.Insert(0, destinationService); }

This code is pretty standard. We have a series of conditions that check the time and set the destinationService object to the correct URL. To produce more maintainable code, we extract the URLs of the three Web services from web.config in the constructor for the class and store them as TokyoUri, LondonUri, and NewYorkUri.

Once we have a Via object that contains the details of the Web service that we’re routing to, we can add this as the first element in the forward path.

That’s how easy it is. After returning from ProcessRequestMessage, the first entry in the forward path is used and the message is routed to the correct destination.

Creating the Web Services

In our custom routing scenarios, we’ll route to the Tokyo.asmx, London.asmx, and NewYork.asmx Web services. These must obviously share the same interface—otherwise, we couldn’t route to them; they can have extra methods on them, but there wouldn’t be much point to adding any because we can route only to methods that are common across all the Web services we’re going to route to. In this case, they all have an Echo method that returns the URL of the executing Web service as well as the route that the message took to that service.

We could cut and paste the code for one Web service into another Web service relatively easily, but we could run into problems doing this. It’s easy to mess up code when you cut and paste. As you saw in Chapter 4, .NET provides a solution to this problem— we can use the wsdl.exe command-line tool to generate a base class for all of the Web services we’re using.

We can use the first Web service that’s created as the basis for the abstract class. With a little name changing in the code, we have a base class, BaseService, that we can use as the basis for all three of the destination Web services—even the Web service that we used to generate the abstract base class. We simply use this class as the base class for our three Web services and override the Echo method with the correct version for the Web service.

WSDL for the Router

Generating the WSDL for a custom router is identical to creating the WSDL for a standard router. We save the WSDL for one of the destination Web services and modify it to match the details of the router we want to use.

The Client

The client that we’re implementing is the second tab of the RoutingClient application, the Custom tab, as shown in Figure 14-9. We have only the Execute button on the tab because all the routing work occurs on the server.


Figure 14-9: The RoutingClient application showing the Custom tab

The code for calling the Web service is no different from what you saw earlier in this chapter and in previous chapters. We simply create an instance of the proxy for the router and call the Echo method. The Web service we call tells us its URL as well as the route the message took to the server, as shown in Figure 14-10.

click to expand
Figure 14-10: Returned message from Tokyo.asmx showing the path taken to the Web service

Nothing to it—all the work is done on the server!

The SOAP Messages

For custom routing, we follow the same paradigm we used for server-controlled routing in that the outgoing Path object is populated with the destination we want to route the message to.

When we make the call to the router, the SOAP message has only the <wsrp:to> element populated with the address of the Web service that we’re calling:

<wsrp:to>http://localhost/wscr/14/RouterD.asmx</wsrp:to>

After we determine the correct outgoing path and the call has been made to the destination Web service, the Routing output filter populates the <wsrp:path> element. For the routing to Tokyo.asmx that we looked at earlier, the SOAP routing header would be populated as follows:

<wsrp:to>http://localhost/wscr/14/RouterD.asmx</wsrp:to> <wsrp:fwd>   <wsrp:via>     http://localhost/wscr/14/Tokyo.asmx   </wsrp:via> </wsrp:fwd> 




Programming Microsoft. NET XML Web Services
Programming MicrosoftВ® .NET XML Web Services (Pro-Developer)
ISBN: 0735619123
EAN: 2147483647
Year: 2005
Pages: 172

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net