wake-up-neo.com

HTTP POST Gibt Fehler zurück: 417 "Erwartung fehlgeschlagen."

Wenn ich versuche, POST zu einer URL zu senden, führt dies zu der folgenden Ausnahme:

Der Remoteserver hat einen Fehler zurückgegeben: (417) Erwartung fehlgeschlagen.

Hier ist ein Beispielcode:

var client = new WebClient();

var postData = new NameValueCollection();
postData.Add("postParamName", "postParamValue");

byte[] responseBytes = client.UploadValues("http://...", postData);
string response = Encoding.UTF8.GetString(responseBytes); // (417) Expectation Failed.

Verwenden eines HttpWebRequest/HttpWebResponse Paar oder ein HttpClient macht keinen Unterschied.

Was ist die Ursache für diese Ausnahme?

209
Saeb Amini

System.Net.HttpWebRequest fügt jeder Anforderung den Header 'HTTP-Header "Expect: 100-Continue"' hinzu, es sei denn, Sie fordern ausdrücklich dazu auf, diese statische Eigenschaft auf false zu setzen:

System.Net.ServicePointManager.Expect100Continue = false;

Einige Server drosseln diesen Header und senden den angezeigten Fehler 417 zurück.

Probier das mal aus.

471
xcud

Ein anderer Weg -

Fügen Sie diese Zeilen zum Konfigurationsabschnitt der Anwendungskonfigurationsdatei hinzu:

<system.net>
    <settings>
        <servicePointManager expect100Continue="false" />
    </settings>
</system.net>
114
Engin Ardıç

Dieselbe Situation und derselbe Fehler können auch bei einem Standardassistenten auftreten, der zur Laufzeit SOAP Web Service Proxy (nicht 100%, wenn dies auch auf dem WCF System.ServiceModel - Stack der Fall ist)] generiert wird :

  • der Endbenutzercomputer ist (in den Interneteinstellungen) für die Verwendung eines Proxys konfiguriert, der HTTP 1.1 nicht versteht
  • der Client sendet dann etwas, das ein HTTP 1.0-Proxy nicht versteht (normalerweise ein Expect -Header als Teil einer HTTP POST - oder PUT -Anforderung aufgrund einer Standardprotokollkonvention zum Senden die Anfrage in zwei Teilen wie in den Erläuterungen hier behandelt )

... was eine 417 ergibt.

Wie in den anderen Antworten beschrieben, kann das Problem durch ein relativ globales Abschalten des zweiteiligen PUT umgangen werden, wenn das spezifische Problem, auf das Sie stoßen, darin besteht, dass der Header Expect das Problem verursacht/POST-Übertragung über System.Net.ServicePointManager.Expect100Continue .

Dies behebt jedoch nicht das gesamte zugrunde liegende Problem - der Stack verwendet möglicherweise immer noch HTTP 1.1-spezifische Dinge wie KeepAlives usw. (obwohl in vielen Fällen die anderen Antworten die Hauptfälle abdecken.)

Das eigentliche Problem ist jedoch, dass der automatisch generierte Code davon ausgeht, dass es in Ordnung ist, HTTP 1.1-Funktionen blind zu verwenden, so wie dies jeder versteht. Um diese Annahme für einen bestimmten Web-Service-Proxy zu beenden, können Sie den Standardwert HttpWebRequest.ProtocolVersion vom Standardwert 1.1 überschreiben, indem Sie eine abgeleitete Proxy-Klasse erstellen, die überschreibt protected override WebRequest GetWebRequest(Uri uri)wie in diesem Beitrag gezeigt : -

public class MyNotAssumingHttp11ProxiesAndServersProxy : MyWS
{
    protected override WebRequest GetWebRequest(Uri uri)
    {
      HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
      request.ProtocolVersion = HttpVersion.Version10;
      return request;
    }
}

(Dabei ist MyWS der Proxy, den der Assistent zum Hinzufügen von Webverweisen an Sie ausgespuckt hat.)


UPDATE: Hier ist ein Werkzeug, das ich in der Produktion verwende:

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 };
    }
}
31
Ruben Bartelink

Verfügt das Formular, das Sie emulieren möchten, über zwei Felder, Benutzername und Kennwort?

Wenn ja, diese Zeile:

 postData.Add("username", "password");

das ist nicht richtig.

sie benötigen zwei Zeilen wie:

 postData.Add("username", "Moose");
postData.Add("password", "NotMoosespasswordreally");

Bearbeiten:

Okay, da dies nicht das Problem ist, besteht eine Möglichkeit, dies zu beheben, darin, mit Fiddler oder Wireshark zu beobachten, was vom Browser erfolgreich an den Webserver gesendet wird, und dies dann mit dem zu vergleichen, was von Ihrem Code gesendet wird. Wenn Sie von .Net zu einem normalen Port 80 wechseln, erfasst Fiddler diesen Datenverkehr weiterhin.

Wahrscheinlich enthält das Formular ein anderes verstecktes Feld, von dem der Webserver erwartet, dass Sie es nicht senden.

5
Moose

Proxy-seitige Lösung: Beim SSL-Handshake-Prozess traten einige Probleme auf, und ich musste meinen Proxy-Server zwingen, Anforderungen über HTTP/1.0 zu senden, um das Problem zu lösen, indem ich dieses Argument in der httpd.conf SetEnv force-proxy-request-1.0 1SetEnv proxy-nokeepalive 1 Danach trat der Fehler 417 auf, da meine Client-Anwendung HTTP/1.1 verwendete und der Proxy gezwungen wurde, HTTP/1.0 zu verwenden. Das Problem wurde behoben, indem dieser Parameter in der httpd.conf auf der Proxy-Seite eingestellt wurde. RequestHeader unset Expect early ohne dass der Client etwas ändern muss, hoffe das hilft.

3
Hytham

Für Powershell ist es

[System.Net.ServicePointManager]::Expect100Continue = $false
2
TNT

Wenn Sie "HttpClient" verwenden und die globale Konfiguration nicht verwenden möchten, um alles zu beeinflussen, was Sie programmieren, können Sie Folgendes verwenden:

 HttpClientHandler httpClientHandler = new HttpClientHandler();
 httpClient.DefaultRequestHeaders.ExpectContinue = false;

Wenn Sie "WebClient" verwenden, können Sie versuchen, diesen Header zu entfernen, indem Sie Folgendes aufrufen:

 var client = new WebClient();
 client.Headers.Remove(HttpRequestHeader.Expect);
1

In meiner Situation scheint dieser Fehler nur aufzutreten, wenn der Computer meines Clients über eine strikte Firewall-Richtlinie verfügt, die verhindert, dass mein Programm mit dem Webdienst kommuniziert.

Die einzige Lösung, die ich finden konnte, besteht darin, den Fehler abzufangen und den Benutzer über das manuelle Ändern der Firewall-Einstellungen zu informieren.

0