This project is read-only.

Custom binding element doesn't work with HttpServiceHost

Topics: Web Api
Dec 20, 2011 at 12:02 PM
Edited Dec 20, 2011 at 12:04 PM

I've extended the RequestInterceptor class (REST Starter Kit) in order to perform some custom authentication. My service is hosted via HttpServiceHost, I have a custom HttpConfiguration using which, I inject the custom binding element (that deploys the RequestInterceptor) as the first binding element in the endpoint, like so:

 CustomBinding authBinding = new CustomBinding(endpoint.Binding);
 authBinding.Elements.Insert(0, new AuthenticationBindingElement());
endpoint.Binding = authBinding;
All this works perfectly, and I can see my interceptor being invoked. However, if my 
interceptor needs to raise an error and send back a reply to the current request 
(without any further processing), this is where the flow fails for me. 
For instance, if I create a new HttpResponse message and set HttpStatusCode, 
this is not conveyed back to the caller, and the caller always sees an InternalServer
 error code (500). I'm using code similar to the one located on this blog :, where I'm creating a 
new Message obect:
replyMessage = Message.CreateMessage(MessageVersion.None, "", 
new BaseFaultBodyWriter(error));
Here my custom BodyWriter is supposed to serialize the object, but I've noticed that 
it's  OnWriteBodyContents method is not being invoked. I then ensure that I set the
HttpResponseMessageProperty on this Message object, and also set status code:
  httpResponse = new HttpResponseMessageProperty();
  httpResponse.StatusDescription = "some error msg";
replyMessage .Properties.Add(HttpResponseMessageProperty.Name, httpResponse);
And I finally set the reply
This doesn't produce the desired result. When I run the same code using the standard
WCF ServiceHost, it works perfectly.
Would appreciate any pointers to make this work. Btw, for my purpose, I can't use the
Web API message handler, so I need to stick to the custom binding element.

Dec 20, 2011 at 5:48 PM

Ok, so I now know why this doesn't work. One of the default binding elements used in Web API is a message encoding element, and this always expects the current message type to be of type HttpMessage. Because I was passing a generic "Message" type in my reply (even though I had sent its HttpResponseMessageProperty), the  binding element failed it.

My options would be to either pass a message of type HttpMessage (which can only be done via the HttpResponseMessage type), or to change the actual code in the Web API source (so even if Message is not HttpMessage, maybe it could look for the HttpResponseMessageProperty and act accordingly). At this point, I'm probably going to stick to the former approach, even though it "dirties" my "generic" request interceptor logic (would have ideally liked to keep it "framework agnostic").