Making One-Way HTTP Requests, Part 2

The article yesterday left off by stating that while the test program works fine with the messaging defaults, things break when we switch to the POX message encoder. Today and tomorrow, we'll look at what goes wrong, why, and how to fix it. To switch to the POX message encoder, I'm going to change the MessageVersion setting of the normal text message encoder that is already in my binding. You can do this by adding the following line to the test client after creating the custom binding.

 binding.Elements.Find<MessageEncodingBindingElement>().MessageVersion = MessageVersion.None;

Now, when I run the test program, I see the correct and expected output on the server.

 HTTP/1.1 POST https://localhost:8000/
::1:1147 --> ::1:8000

[Headers]
Connection: Keep-Alive
Content-Length: 126
Content-Type: application/xml; charset=utf-8
Expect: 100-continue
Host: localhost:8000

[Request]
<Ping xmlns="https://tempuri.org/">
  <clientInfo>my info</clientInfo>
  <lastSeen>2006-08-15T00:22:36.528375-07:00</lastSeen>
</Ping>

All of the SOAP goo is gone from the request. Compared to the request we saw yesterday, the only thing left in the request is what was formerly the contents of the body tag. However, on the client side, there's an exception being thrown after the message gets sent.

Unhandled Exception: System.ServiceModel.ProtocolException: A response was received from a one-way send over the underlying IRequestChannel. Make sure the remote endpoint has a compatible binding at its endpoint (one that contains OneWayBindingElement).

 Server stack trace:
   at System.ServiceModel.Channels.RequestOneWayChannelFactory.RequestOutputChannel.ValidateResponse(Message response)
   at System.ServiceModel.Channels.RequestOneWayChannelFactory.RequestOutputChannel.OnSend(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.OutputChannel.Send(Message message, TimeSpan timeout)

It's fairly easy to figure out what happened from the message and stack trace although it may not be obvious why. Inside the OneWay channel, there is validation that the system is truly acting in a one-way fashion. If you look at the code for the ValidateResponse method, you would see that it is essentially checking that the response message is null. In this case, we got a reply back from the server even though we were not expecting it to send anything back. Remember, the server knows nothing about WCF and behaves exactly the same for every request regardless of what you throw in the message. The only thing we changed between yesterday and today is the message encoder.

Tomorrow, we'll look at why this happens with the POX message encoder and how to fix it.

Next time: Making One-Way HTTP Requests, Part 3