219 votes

HTTP POST Renvoie L'Erreur: 417 "Échec de l'Attente." (C#)

J'essaie de me connecter à un site web à l'aide de HTTP POST. Je suis sûr que le site ne nécessite que deux POST champs: nom d'utilisateur et mot de passe; il n'y a pas de champs cachés.

Je reçois l'exception suivante lorsque je tente de lire la réponse:

"Le serveur distant a retourné une erreur: (417) Échec De L'Attente."

J'ai essayé les deux, HTTPWebResponse/HttpWebRequest et WebClient.

Voici un exemple de code que j'utilise:

WebClient client = new WebClient();

NameValueCollection postData = new NameValueCollection();
postData.Add("username", "myUserName");
postData.Add("password", "myPassword");

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

Quelle est la cause de cette exception?

482voto

xcud Points 6878

Système.Net.HttpWebRequest ajoute l'en-tête 'en-tête HTTP "Attendre: 100-continue" " pour chaque demande, sauf si vous demandez explicitement de ne pas en définissant cette propriété statique de faux:

System.Net.ServicePointManager.Expect100Continue = false;

Certains serveurs d'étranglement sur cet en-tête et l'envoi de la 417 erreur que vous voyez.

Donner un coup de feu.

116voto

Engin Ardıç Points 1447

Un autre moyen, ajoutez ces lignes à votre fichier de config à la section de configuration;

<system.net>
    <settings>
        <servicePointManager expect100Continue="false" />
    </settings>
</system.net>

31voto

Ruben Bartelink Points 23945

Cette même situation et l'erreur peut également être le cas avec un par défaut de l'assistant généré SAVON de proxy de Service Web (pas à 100% si c'est également le cas sur la WCF System.ServiceModel pile) lorsqu'au moment de l'exécution:

  • l'utilisateur de la machine est configuré dans les Paramètres Internet) pour utiliser un proxy qui ne comprennent pas HTTP 1.1
  • le client finit par l'envoi de quelque chose qui un HTTP 1.0 proxy ne comprennent pas (souvent une Expect d'en-tête dans le cadre d'un HTTP POST ou PUT la demande en raison d'une norme de protocole de la convention de l'envoi de la demande, en deux parties, comme indiqué dans les Remarques ici)

... ce qui donne un 417.

Abordés dans les autres réponses, si le problème que vous rencontrer, c'est que l' Expect - tête est à l'origine du problème, alors que problème spécifique peut être acheminé de façon à contourner en faisant un relativement mondial de l'arrêt du deux-partie PUT/POST transmission via System.Net.ServicePointManager.Expect100Continue.

Toutefois, cela ne résout pas le terminer problème sous - jacent- la pile peut encore utiliser HTTP 1.1 choses spécifiques comme les connexions actives etc. (bien que, dans de nombreux cas, les autres réponses ne couvrent les principaux cas.)

Le réel problème est que le code généré automatiquement suppose que c'est OK pour aller aveuglément à l'aide de HTTP 1.1 installations comme tout le monde comprend cela. Pour arrêter cette hypothèse pour un proxy de Service Web, on peut changer de remplacer la valeur par défaut sous-jacent HttpWebRequest.ProtocolVersion de la valeur par défaut de 1.1 par la création d'un dérivé de la classe Proxy qui remplace protected override WebRequest GetWebRequest(Uri uri) comme indiqué dans ce post:-

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

(où MyWS est le proxy de l'Ajouter une Référence Web assistant recraché à vous.)


Mise à JOUR: Voici une impl je suis une utilisation en 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 };
    }
}

6voto

Jon Skeet Points 692016

Vous êtes actuellement en détachement "nom d'utilisateur" en tant que clé et "mot de passe" comme valeur. Voulez-vous dire

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

?

5voto

Moose Points 3792

Le formulaire que vous essayez d'imiter avoir deux champs, le nom d'utilisateur et le mot de passe?

Si oui, cette ligne:

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

n'est pas correct.

vous auriez besoin de deux lignes comme:

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

Edit:

Bon, puisque ce n'est pas le problème, un moyen de remédier à cela est d'utiliser quelque chose comme Fiddler ou Wireshark pour regarder ce qui est envoyée au serveur web à partir du navigateur avec succès, puis de les comparer à ce qui est envoyé à partir de votre code. Si vous allez à la normale le port 80 .Net, Violoniste sera encore la capture de ce trafic.

Il y a probablement certains autres champ caché dans le formulaire que le serveur web s'attend à ce que vous n'êtes pas d'envoi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X