This same situation and error can also arise with a default wizard generated SOAP Web Service proxy (not 100% if this is also the case on the WCF System.ServiceModel
stack) when at runtime:
- the end user machine is configured (in the Internet Settings) to use a proxy that does not understand HTTP 1.1
- the client ends up sending something that a HTTP 1.0 proxy doesnt understand (commonly an
Expect
header as part of a HTTP POST
or PUT
request due to a standard protocol convention of sending the request in two parts as covered in the Remarks here)
... yielding a 417.
As covered in the other answers, if the specific issue you run into is that the Expect
header is causing the problem, then that specific problem can be routed around by doing a relatively global switching off of the two-part PUT/POST transmission via System.Net.ServicePointManager.Expect100Continue
.
However this does not fix the complete underlying problem - the stack may still be using HTTP 1.1 specific things such as KeepAlives etc. (though in many cases the other answers do cover the main cases.)
The actual problem is however that the autogenerated code assumes that it's OK to go blindly using HTTP 1.1 facilities as everyone understands this. To stop this assumption for a specific Web Service proxy, one can change override the default underlying HttpWebRequest.ProtocolVersion
from the default of 1.1 by creating a derived Proxy class which overrides protected override WebRequest GetWebRequest(Uri uri)
as shown in this post:-
public class MyNotAssumingHttp11ProxiesAndServersProxy : MyWS
{
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
request.ProtocolVersion = HttpVersion.Version10;
return request;
}
}
(where MyWS
is the proxy the Add Web Reference wizard spat out at you.)
UPDATE: Here's an impl I'm using in production:
class ProxyFriendlyXXXWs : BasicHttpBinding_IXXX
{
public ProxyFriendlyXXXWs( Uri destination )
{
Url = destination.ToString();
this.IfProxiedUrlAddProxyOverriddenWithDefaultCredentials();
}
// Make it squirm through proxies that don't understand (or are misconfigured) to only understand HTTP 1.0 without yielding HTTP 417s
protected override WebRequest GetWebRequest( Uri uri )
{
var request = (HttpWebRequest)base.GetWebRequest( uri );
request.ProtocolVersion = HttpVersion.Version10;
return request;
}
}
static class SoapHttpClientProtocolRealWorldProxyTraversalExtensions
{
// OOTB, .NET 1-4 do not submit credentials to proxies.
// This avoids having to document how to 'just override a setting on your default proxy in your app.config' (or machine.config!)
public static void IfProxiedUrlAddProxyOverriddenWithDefaultCredentials( this SoapHttpClientProtocol that )
{
Uri destination = new Uri( that.Url );
Uri proxiedAddress = WebRequest.DefaultWebProxy.GetProxy( destination );
if ( !destination.Equals( proxiedAddress ) )
that.Proxy = new WebProxy( proxiedAddress ) { UseDefaultCredentials = true };
}
}
Expect
header which by default gets added asExpect100Continue
istrue
by default. – Ruben Bartelink