I’ve been working this week on implementing some custom WCF transport channels. The one I was working on initially is a two-way send channel, so, naturally, I decided to begin by having my channel implement the IRequestChannel shape.
This was working fine until I decided to try a one-way operation on top of my two-way channel, which was interesting because I was not implementing an equivalent part of the transport supporting IOutputChannel.
I was expecting it to fail right from the start, but, surprisingly enough, it almost worked. That is, the transport channel was called, executed, and only bombed when the WCF stack ran into the unexpected response message. The error message I was seeing was something like this:
System.ServiceModel.ProtocolException: The one-way operation returned a non-null message with Action=''.
Looking around, I realized a couple of things: First of all, the built-in HTTP transports in WCF also implement only IRequestChannel, and yet, somehow, they still manage to work just fine in this case.
The second thing that came to mind was that I was using a custom MessageEncoder. Granted, it was a very rough and crappy encoder, but it was mostly enough for me to test a few things about my custom transport.
That last part sparked something deep in my memory: I seemed to vaguely remember something about encoders that might be related, so I turned right away to the best source for everything WCF related: Nicholas Allen’s blog.
Fortunately, Dr. Nick did not disappoint! In one of his articles about writing a custom POX Message Encoder, he included this little gem:
“One of the properties of the standard message encoders is that they only surface up messages that have a non-empty message body.”
That was indeed what I was seeing: My custom transport was indeed returning a message from IRequestChannel.Request(), but it had no content at all (something particular to the kind of request I was making over the one-way channel).
Once I changed my custom encoder to ignore the empty message, it worked just fine.