Ta sama sytuacja i błąd mogą również wystąpić w przypadku domyślnego generowanego przez kreatora proxy usługi SOAP Web Service (nie w 100%, jeśli dotyczy to również System.ServiceModel
stosu WCF ) w czasie wykonywania:
- komputer użytkownika końcowego jest skonfigurowany (w Ustawieniach internetowych) do używania serwera proxy, który nie rozumie protokołu HTTP 1.1
- klient ostatecznie wysyła coś, czego serwer proxy HTTP 1.0 nie rozumie (zwykle
Expect
nagłówek jako część HTTP POST
lub PUT
żądania ze względu na standardową konwencję protokołu wysyłania żądania w dwóch częściach, jak opisano w uwagach tutaj )
... co daje 417.
Jak opisano w innych odpowiedziach, jeśli konkretnym problemem, na który Expect
natrafisz, jest to, że przyczyną problemu jest nagłówek, to ten konkretny problem można rozwiązać, wykonując względnie globalne wyłączenie dwuczęściowej transmisji PUT / POST przez System.Net.ServicePointManager.Expect100Continue
.
Nie rozwiązuje to jednak całego podstawowego problemu - stos może nadal używać specyficznych dla HTTP 1.1 rzeczy, takich jak KeepAlives itp. (Choć w wielu przypadkach inne odpowiedzi obejmują główne przypadki).
Faktyczny problem polega jednak na tym, że automatycznie generowany kod zakłada, że można ślepo korzystać z urządzeń HTTP 1.1, ponieważ wszyscy to rozumieją. Aby zatrzymać to założenie dla konkretnego serwera proxy usługi sieci Web, można zmienić zastąpienie domyślnego elementu bazowego HttpWebRequest.ProtocolVersion
od domyślnego 1.1 , tworząc pochodną klasę proxy, która zastępuje, jak pokazano w tym poście : -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;
}
}
(gdzie MyWS
jest serwer proxy, na który wypluł cię kreator dodawania odnośników internetowych).
AKTUALIZACJA: Oto implik, którego używam w produkcji:
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 };
}
}