IReplyChannel and “null” replies
I mentioned in an earlier post how the Service Model Runtime normalizes different channel shapes based on the requirements of your OperationContract. One of the adaptations the Service Model Runtime provides is the ability to use one-way methods over IRequestChannel and IReplyChannel.
For example, let’s say you have method such as:
OperationContract(IsOneWay=true]void SendUpdate(string update);If you want to expose this method over BasicHttpBinding, how does that work? HTTP is fundamentally request-reply based, and as such offers up only IRequestChannel and IReplyChannel.
To address this scenario, part of the model for request-reply is a paradigm whereby a channel can optionally support “null” responses. This is exposed through the programming model by calling IRequestContext.[Begin]Reply(null). As an additional convenience, if you call IRequestContext.Close() without having sent a reply we will call Reply(null) on your behalf.
HTTP signals a “null” response on the wire by sending a “202 Accepted” with no entity body. Note that for interop purposes we are lax on the client and allow any 200-level response without an entity body to signal null response. TCP/Pipes send a .Net Framing ACK with no entity body. A message-level protocol for request reply can designate a particular schema/action for an “ACK Message” to signal a null response.
On the client you should check for a null return value from IRequestChannel.SendRequest(). For example:
Messagereply = requestChannel.SendRequest(request);if(reply ==null) {Console.WriteLine(”Called a one-way method.”); }else{Console.WriteLine(”Called a two-way method.”); }
ServiceModel, as well as our forthcoming OneWayBindingElement leverage the “null” response in order to achieve mapping request-response message exchanges to one-way.
July 6th, 2006 at 1:22 pm
[…] The service will release the connection (or complete the HTTP request/response by replying with null, etc) before dispatching to user code. If the operation is not marked with IsOneWay then our Dispatcher won’t reply until the Operation has completed […]
December 14th, 2006 at 8:14 pm
[…] Abort()/Close() — If the associated HTTP Channel Listener has been disposed, then channel.Abort will in turn call HttpRequestContext.Abort() on any RequestContexts that have not been replied to. This will cause http.sys to abort the underlying TCP socket. If the HTTP Channel Listener has not been disposed then channel.Abort() simply transfers ownership of these outstanding request contexts back to the channel listener. Close() actually performs in the same fashion, since calling requestContext.Close() in this case would have the unexpected side-effect of sending a 202 Accepted response. […]