On my last post I put out some questions on the design of URI syntaxes for Windows Communication Foundation transport channels. Scott Seely posted a very interesting response and I wanted to comment a bit on it.
First Scott says:
"The address element can take a set of extra headers-- see EndpointAddress.Headers. These headers can also be passed in as part of the config object model. This feature exists to handle scenarios like yours. The URI should contain enough information to hit the endpoint."
Scott's referring to the EndpointAddress class, which can indeed contain optional headers "used to provide additional, more detailed addressing information to identify or interact with the endpoint". See here for a bit more details as well. The big about "these headers can also be passed in as ppart of the config object model" did confuse me a bit; care to point to relevant docs/examples?
One thing Scott is totally right here is his last part about the URI containing only enough information to hit the endpoint. For example, if you had an SMTP transport, for sending messages the logical addressing scheme would be centered around the email address to send the message to; but, you'd also need to know the hostname and port where you'll find an SMTP server listening. However, the last bit would be a private configuration detail to the client, and would never need to be exposed to the outside. This gives me some ideas to work with already!
Scott's comment also made me think about something I had not been considering before. See, those headers in the EndpointAddress are very useful in scenarios where WS-Addressing is involved. In particular, in a fully asynchronous, disjoined request/reply scenario, you can use them to pass extra information needed by the other endoint to reply to your original message, as part of the ReplyTo header. For an asynchronous mechanism like I'm working on, looking at supporting that would be very interesting and I can think of a couple of ways to leverage that.
Scott goes on to say:
"As for asymmetry in the URI scheme, what you need to do is tell any clients, via policy and WSDL, how to connect to your endpoint. So long as you can express that asymettry in a way that the client can work with it with no ill effects, you should be fine."
That's the crux of the issue I have with my current scheme. The URI assymmetry I talked about is partially caused by the underlying transport: The message sender needs to specify some information, but the message receiver needs to specify different information. How come?
The thing here to understand is that the protocol I'm working with has routing intermediaries:
Those routing intermediaries don't know anything about WCF or SOAP (and much less WS-*). All they know is how to receive a message from a message publisher (which in our case would be a WCF client proxy) and route them to somewhere a message consumer (which in our case would be a WCF service) based on a configured criteria.
Furthermore, the information the message publisher needs to provide to establish a successful connection to the router and send a message is not the same a message consumer needs to provide to successfully connect to the router and receive a message (yes, for this protocol receive-side endpoints need to actively connect to the router and request message delivery).
One important fact that can be derived from this is that because of the presence of the intermediate router (and there could be more than one involved), the client and server addressing schemes will not be the same. That's because there's a very loose coupling between the message publishers (clients) and message consumers (services) because one does not know anything about the other and can't address it directly.
And this directly affects the WSDL generation issue that Scott mentions. If the client can't address the service endpoint directly, how could the service generate a WSDL description of it that is immediately useful for a potential client to use without it having to always rewrite the address specified in the service description? This is definitely something that I had briefly thought about before, but didn't give it much importance originally, but Scott's comment makes me realize I should focus a bit more on that.
I can think of at least two ways to work around this issue by taking advantage of a couple of features at the protocol level, but I'm not entirely happy with either one. It might very well be that I'll need to constraint the channel a bit for the WSDL generation but it should still prove useful, I think.