Question

Lorsque j'essaie de POST sur une URL, l'exception suivante se produit :

Le serveur distant a renvoyé une erreur :(417) L’attente a échoué.

Voici un exemple de code :

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.

Utiliser un HttpWebRequest/HttpWebResponse paire ou un HttpClient cela ne fait aucune différence.

Quelle est la cause de cette exception ?

Était-ce utile?

La solution

System.Net.HttpWebRequest ajoute l'en-tête "En-tête HTTP" Attendez-vous :100-Continuer"' à chaque requête, sauf si vous lui demandez explicitement de ne pas le faire en définissant cette propriété statique à faux :

System.Net.ServicePointManager.Expect100Continue = false;

Certains serveurs s'étouffent avec cet en-tête et renvoient l'erreur 417 que vous voyez.

Essayez-le.

Autres conseils

Autrement -

Ajoutez ces lignes à la section de configuration du fichier de configuration de votre application :

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

Cette même situation et cette même erreur peuvent également survenir avec un proxy de service Web SOAP généré par un assistant par défaut (et non à 100 % si c'est également le cas sur WCF). System.ServiceModel pile) lors de l'exécution :

  • la machine de l'utilisateur final est configurée (dans les paramètres Internet) pour utiliser un proxy qui ne comprend pas HTTP 1.1
  • le client finit par envoyer quelque chose qu'un proxy HTTP 1.0 ne comprend pas (généralement un Expect en-tête dans le cadre d'un HTTP POST ou PUT demande en raison d'une convention de protocole standard consistant à envoyer la demande en deux parties comme indiqué dans les remarques ici)

...donnant un 417.

Comme indiqué dans les autres réponses, si le problème spécifique que vous rencontrez est que le Expect est à l'origine du problème, alors ce problème spécifique peut être résolu en effectuant une désactivation relativement globale de la transmission PUT/POST en deux parties via System.Net.ServicePointManager.Expect100Continue.

Cependant, cela ne résout pas complètement le problème sous-jacent : la pile peut toujours utiliser des éléments spécifiques à HTTP 1.1 tels que KeepAlives, etc.(bien que dans de nombreux cas, les autres réponses couvrent les cas principaux.)

Le véritable problème est cependant que le code généré automatiquement suppose qu'il est acceptable d'utiliser aveuglément les fonctionnalités HTTP 1.1 comme tout le monde le comprend.Pour arrêter cette hypothèse pour un proxy de service Web spécifique, on peut remplacer le sous-jacent par défaut HttpWebRequest.ProtocolVersion du défaut de 1.1 en créant une classe Proxy dérivée qui remplace protected override WebRequest GetWebRequest(Uri uri) comme le montre 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 que l'assistant d'ajout de référence Web vous a craché.)


MISE À JOUR:Voici un impl que j'utilise 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 };
    }
}

Le formulaire que vous essayez d’émuler comporte-t-il deux champs, nom d’utilisateur et mot de passe ?

Si oui, cette ligne :

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

n'est pas correcte.

il vous faudrait deux lignes comme :

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

Modifier:

D'accord, puisque ce n'est pas le problème, une façon de résoudre ce problème est d'utiliser quelque chose comme Fiddler ou Wireshark pour surveiller avec succès ce qui est envoyé au serveur Web à partir du navigateur, puis de comparer cela à ce qui est envoyé depuis votre code.Si vous accédez à un port 80 normal depuis .Net, Fiddler capturera toujours ce trafic.

Il y a probablement un autre champ caché sur le formulaire que le serveur Web s'attend à ce que vous n'envoyiez pas.

Solution côté proxy, j'ai rencontré quelques problèmes dans le processus de négociation SSL et j'ai dû forcer mon serveur proxy à envoyer des requêtes via HTTP/1.0 pour résoudre le problème en définissant cet argument dans le fichier httpd.conf. SetEnv force-proxy-request-1.0 1 SetEnv proxy-nokeepalive 1 après cela, j'ai été confronté à l'erreur 417 car l'application de mon client utilisait HTTP/1.1 et le proxy était obligé d'utiliser HTTP/1.0, le problème a été résolu en définissant ce paramètre dans le httpd.conf du côté proxy RequestHeader unset Expect early sans avoir besoin de changer quoi que ce soit du côté client, j'espère que cela vous aidera.

Pour Powershell, c'est

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

Si vous utilisez "Client HTTP", et vous ne souhaitez pas utiliser la configuration globale pour affecter tout votre programme que vous pouvez utiliser :

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

Je tu utilises "Client Web" Je pense que vous pouvez essayer de supprimer cet en-tête en appelant :

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

Dans ma situation, cette erreur semble se produire uniquement si l'ordinateur de mon client dispose d'une politique de pare-feu stricte, qui empêche mon programme de communiquer avec le service Web.

La seule solution que j'ai pu trouver est de détecter l'erreur et d'informer l'utilisateur de la modification manuelle des paramètres du pare-feu.

L'approche web.config fonctionne pour les appels des services de formulaire InfoPath aux règles activées pour le service Web IntApp.

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top