Blogger :
Thinktecture Blog
All posts :
All posts by Thinktecture Blog
Category :
WSCF/WCF
Blogged date : 2007 May 25
During the past few days I came across some SOAP routing
intermediary implementations (of course running on WCF ;)) and each of them
were trying to route the WCF messages by changing the “To” WS-Addressing header
in the message. In some cases this even required completely reconstructing the
message by reading its body contents. This actually made me think about the
basics once again. What actually happens in the real routers? For example, does
Windows TDI driver for TCP/IP change the destination IP to your router’s IP
after looking at the routing table? No! Instead, the transport transmits the traffic
to the appropriate IP as specified in the routing table. Then the router reads
the destination IP in the incoming TCP segments and forwards the traffic to the
next network hop according to the routing table in the router itself. So essentially,
the router is a device that simply forwards messages without tweaking them. Likewise
this should be the theory behind the SOAP routers as well (of course SOAP works
at a much higher level and you can divert this approach to meet your custom
needs. But I’m talking about the routing in general).
So how exactly you can do this in WCF? The answer is hidden
in an attribute that you might not pay too much attention in your everyday WCF
adventures ;). When you configure an endpoint you can actually, specify the
service address as well as the actual listening address as follows.
[service endpoint]
<endpoint address="http://localhost:8000/service/dummyendpoint.svc"
listenUri="http://localhost:8000/service/actualendpoint.svc"
contract="…"
binding="…"
bindingConfiguration="…"
/>
When you start your service the underlying transport
actually uses the address specified in the listenUri to listen to the incoming
traffic (if this is not specified, it uses the endpoint address by default).
The service address on the other hand is the one which goes in the
WS-Addressing “TO” header. This address is validated by service model layer to
make sure that the messages that arrive at the endpoint are truly intended for
this service (otherwise you’ll get the address filter mismatch error… remember
that? ;)). So with these two attributes in our hands we can successfully model
the aforementioned routing in the SOAP level as well. You can do it by having
your router service actually listening on the endpoint address specified in the
service (see below).
[router endpoint]
<endpoint address="http://localhost:8000/service/dummyendpoint.svc"
contract="…"
binding="…"
bindingConfiguration="…"
/>
Then you can simply forward the messages to the actual
service endpoints according your routing rules. For example, you can determine
a message to the above service endpoint by looking at the action header of the
incoming message and forward it to the service by making a channel to http://localhost:8000/service/actualendpoint.svc
endpoint (which is the actual endpoint of our service). Also note that
this way, no matter how many intermediaries the message passes through the
WS-Addressing “TO” header remains consistent.
When I started writing this post I intended to provide a very
rough sample that I created couple of months ago (in fact I gave up re-inventing
the wheel after seeing Shy Cohen’s wonderful lossy router ;)). But then I
realized that the SDK routing sample perfectly demonstrates this. So
take a look at it to get a better picture on it.
Have fun!