Exposing a WCF HTTP Service on the AppFabric Service Bus

Topics: Web Api
Nov 2, 2010 at 12:47 AM

In my opinion, it is arguable if WCF is the best stack where to add great HTTP support. However, one of the advantages of this choice might be the integration with other WCF-able technologies, namely AppFabric Service Bus.

I've tried and succeed to expose a simple WCF HTTP service on the Service Bus, however I've found some roadblocks:

1) The WebHttpServiceHost does not allow the explicit addition of service endpoints (via addServiceEndpoint), because of the way it creates the default endpoints (explicitly obtaining the operation contract).

2) In order to expose on the Service Bus, I have to use a custom binding composed by:

a) The WCF HTTP HttpMessageEncodingBindingElement, since the upper service model components expect a HttpMessage and not a regular Message.

b) The  HttpRelayTransportBindingElement, so the service is exposed remotely on the service bus.

However, the HttpMessageEncodingBindingElement class is internal.

3) The Service Bus transport channel expects the message to behave as a regular Message instance, namely is expects the OnGetReaderAtBodyContents method to behave correctly. However, in HttpMessage, this method throws a NotSupportedException.

Regards

Pedro

Nov 2, 2010 at 4:36 AM

The relay bindings don't really let you slot a custom message encoder into the stack. We'll take the encoder and even copy settings, but we won't use it - because the messages we realy down are not read off the wire but rather from the body of a wrapper messages. We're looking to change that in a future version of Service Bus. Right now we are producing messages that have the correct HTTP request and reply properties, but we're obviously not producing the HttpMessage. The only way to fix that would be to slot in a custom IReplyChannel channel and swap out the message as it flows up/down the stack.

Coordinator
Nov 2, 2010 at 4:46 AM

 

Not sure if this helps, but we do expose extension methods for getting to the HttpMessage from a Message and vice versa. If you look through the code you will find them...ToHttpRequestMessage, ToHttpResponseMessage.

Coordinator
Nov 2, 2010 at 4:51 AM

Looks like it doesn't help based on point 3......

Nov 2, 2010 at 1:00 PM

Hi Clemens,

Thanks for the reply.

According to my analysis of the WCF HTTP source code (thanks for that Glenn!), the HttpMessageEncodingBindingElement already inserts a IReplyChannel that converts from a regular Message to an HttpMessage (if needed) on the up flow.

The problem is in the response. This IReplyChannel does copies the headers from the HttpResponseMessage into an HttpResponseMessageProperty, but does not change the message: the message that flows down is still an HttpMessage. When the relay transport tries to get a XmlReader to the body of this message, a NotSupportException is thrown.

My change was to, in the down flow, translate from an HttpMessage to a regular Message, by using the StreamMessageHelper.CreateMessage method, as you suggested.

However, this now breaks when using the HttpMessageEncoder (non relay scenario), since this encoder expects an HttpMessage.

Probably the cleanest way to solve this is to create a new binding element, to use only with the relay transport, that results on a IReplyChannel that does the down flow translation.

Thanks

Pedro

Nov 9, 2010 at 4:10 AM

Et al,

I'm in no way qualified enough to understand the nuances that are discussed here... but I would like to expose a WCF HTTP service on the Service Bus.  My thought here is that I'm designing a cloud application that could see extreme spike in traffic during specific (and known) periods of time.  I need to accept these requests serially, do one piece of work, and then let it spread out across a number worker roles.  Due to the volume, I need to make this route as efficient as possible, and don't really want to have IIS in the middle (between the Service Bus, and the WCF Endpoint).

I'm stuck on HTTP, as the other service I'm relying on does a REST API.

Is this my most efficient route?

Regards,
Richard