Rants and tutorials about the freshest technologies! With commentary from d-roc and Vargo. Prepare to take sides.

Sunday, May 3, 2009

Oh noes! Expectation Failed (417) in my WCF service at Tully’s

Just when I thought my WCF service was working properly with regard to different network set-ups (i.e. my work network versus my home network), I found an annoying error occurring whenever I try to call one of my service methods.

Aside: Is that the proper terminology? Do I say: “Whenever I call a service method” or instead do I say: “Whenever I connect to my service” or : “Whenever I access my service” ? I’m not sure of the proper lingo.

For the benefit of search engines, that’s: “ProcolException was unhandled. The remote server returned an unexpected response: (417) Expectation failed.”

I verified (via remote desktop) that my home PC is still getting a proper response from the service. So what’s going on? Why am I unable to live up to my web service’s expectations when I’m on my laptop at Tully’s? Well, either it has something to do with my local system configuration, or it has something to do with the network settings here. I don’t really have a convenient way to test another network here, so I’m going to work on the hypothesis that it has something to do with Tully’s wifi network configuration. This seems especially likely given that my web browser is having a heck of a time loading web pages fully. Nevertheless, I don’t want to lazily write this off as an extreme case. I’ll need to use Google to get to the bottom of this.

So, after looking at Google, I’ve found several forums in which people have had a similar problem, and a solution which seems to work is described on my new favorite code-help site, stackoverflow.com:

System.Net.HttpWebRequest adds the header 'HTTP header "Expect: 100-Continue"' to every request unless you explicitly ask it not to by setting this static property to false:

System.Net.ServicePointManager.Expect100Continue = false;

Some servers choke on that header and send back the 417 error you're seeing.

Sure enough, I added this line before my call to the WCF service and everything worked as expected. Of course, it’s still basically magic to me. I understand little about how these requests and responses behave. MSDN demystifies it a little bit more:

When this property is set to true, client requests that use the POST method expect to receive a 100-Continue response from the server to indicate that the client should send the data to be posted. This mechanism allows clients to avoid sending large amounts of data over the network when the server, based on the request headers, intends to reject the request.

For example, assume the Expect100Continue property is false. When the request is sent to the server, it includes the data. If, after reading the request headers, the server requires authentication and must send a 401 response, the client must resend the data with proper authentication headers.

If this property is true, the request headers are sent to the server. If the server has not rejected the request, it sends a 100-Continue response signaling that the data can be transmitted. If, as in the preceding example, the server requires authentication, it sends the 401 response and the client has not unnecessarily transmitted the data.

Changing the value of this property does not affect existing ServicePoint objects. Only new ServicePoint objects created after the change are affected.

The Expect 100-Continue behavior is fully described in IETF RFC 2616 Section 10.1.1.