System.ServiceModel
これと同じ状況とエラーは、実行時に既定のウィザードで生成された SOAP Web サービス プロキシでも発生する可能性があります (WCF スタックでも同じ場合は 100% ではありません)。
- HTTP 1.1 を認識しないプロキシを使用するようにエンド ユーザーのマシンが (インターネット設定で) 構成されている
- クライアントは、HTTP 1.0 プロキシが理解できないものを送信することになります (一般的に、HTTPまたはリクエスト
Expect
の一部としてのヘッダーは、ここの備考で説明されているように、リクエストを 2 つの部分に分けて送信するという標準プロトコル規則によるものです) 。POST
PUT
... 417 を生成します。
他の回答で説明されているように、Expect
ヘッダーが問題を引き起こしているという特定の問題が発生した場合、その特定の問題は、 を介した 2 部構成の PUT/POST 送信を比較的グローバルにオフにすることで回避できますSystem.Net.ServicePointManager.Expect100Continue
。
ただし、これは根本的な問題を完全に解決するものではありません。スタックは、KeepAlive などの HTTP 1.1 固有のものを使用している可能性があります (ただし、多くの場合、他の回答は主なケースをカバーしています)。
しかし、実際の問題は、自動生成されたコードが、HTTP 1.1 機能をやみくもに使用しても問題ないと想定していることです。これは誰もが理解していることです。特定の Web サービス プロキシに対するこの仮定を停止するには、この投稿に示されているようにオーバーライドする派生プロキシ クラスを作成することにより、デフォルトの1.1HttpWebRequest.ProtocolVersion
からデフォルトのオーバーライドを変更できます。protected override WebRequest GetWebRequest(Uri uri)
public class MyNotAssumingHttp11ProxiesAndServersProxy : MyWS
{
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
request.ProtocolVersion = HttpVersion.Version10;
return request;
}
}
( MyWS
Web 参照の追加ウィザードが吐き出したプロキシはどこにありますか。)
更新: これは私が本番環境で使用している impl です:
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 };
}
}