HTTP POST renvoie L'erreur: 417 " L'attente a échoué."
Lorsque j'essaie de poster sur une URL, il en résulte l'exception suivante:
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.
L'utilisation d'une paire HttpWebRequest/HttpWebResponse
ou d'un HttpClient
ne fait aucune différence.
Qu'est-ce qui cause cette exception?
9 réponses
System. Net. HttpWebRequest ajoute l'en-tête 'HTTP header" Expect: 100-Continue" ' à chaque requête sauf si vous le demandez explicitement en définissant Cette propriété statique à false:
System.Net.ServicePointManager.Expect100Continue = false;
Certains serveurs s'étouffent sur cet en-tête et renvoient l'erreur 417 que vous voyez.
Donner un coup de feu.
Une autre façon -
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 erreur peuvent également survenir avec un proxy de service Web SOAP généré par l'assistant par défaut (pas à 100% Si c'est également le cas sur la pile WCF System.ServiceModel
) 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 en-tête
Expect
dans le cadre D'une requête HTTPPOST
ouPUT
en raison d'un protocole standard convention d'envoi de la demande en deux parties comme couvert dans les remarques ici )
... donnant un 417.
Comme couvert dans les autres réponses, si le problème spécifique que vous rencontrez est que l'en-tête Expect
cause le problème, alors ce problème spécifique peut être acheminé en désactivant relativement globalement la transmission PUT/POST en deux parties via System.Net.ServicePointManager.Expect100Continue
.
Cependant, cela ne résout pas le problème sous-jacent complet-le stack peut toujours utiliser des choses spécifiques à HTTP 1.1 telles que KeepAlives, etc. (bien que dans de nombreux cas, les autres réponses couvrent les cas principaux.)
Le problème réel est cependant que le code généré automatiquement suppose qu'il est correct d'utiliser aveuglément les installations HTTP 1.1 car tout le monde le comprend. Pour arrêter cette hypothèse pour un proxy de service Web spécifique, on peut changer remplacer le sous-jacent par défautHttpWebRequest.ProtocolVersion
de la valeur par défaut de 1.1 en créant un Proxy dérivé classe 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 que L'Assistant D'ajout de référence Web vous a craché.)
UPDATE: 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 a-t-il deux champs, Nom d'utilisateur et 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");
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 regarder ce qui est envoyé au serveur web à partir du navigateur avec succès, puis comparez cela à ce qui est envoyé à partir de votre code. Si vous allez à une normale port 80 de. Net, Fiddler va toujours capturer ce trafic.
Il y a probablement un autre champ caché sur le formulaire que le serveur web attend que vous n'envoyez pas.
Solution du côté du proxy, j'ai rencontré quelques problèmes dans le processus de handshake SSL et j'ai dû forcer mon serveur proxy à envoyer des requêtes en utilisant HTTP / 1.0 Pour résoudre le problème en définissant cet argument dans le httpd.conf SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
Après cela, j'ai fait face à l'erreur 417 car l'application de mes clients utilisait HTTP/1.1 et le proxy a été forcé 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, espérons cela aide.
Si vous utilisez " HttpClient ", et que vous ne souhaitez pas utiliser la configuration globale pour affecter tout ce que vous pouvez utiliser:
HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClient.DefaultRequestHeaders.ExpectContinue = false;
I vous utilisez " WebClient " je pense que vous pouvez essayer de supprimer cet en-tête en appelant:
var client = new WebClient();
client.Headers.Remove(HttpRequestHeader.Expect);
Pour Powershell c'est
[System.Net.ServicePointManager]::Expect100Continue = $false
Le web.l'approche config fonctionne pour les appels InfoPath form services aux règles activées par le service Web IntApp.
<system.net>
<defaultProxy />
<settings> <!-- 20130323 bchauvin -->
<servicePointManager expect100Continue="false" />
</settings>
</system.net>
Dans Ma situation, cette erreur semble se produire uniquement si l'ordinateur de mon client a une politique de pare-feu stricte, ce qui empêche mon programme de communiquer avec le service web.
Donc, la seule solution que j'ai pu trouver est d'attraper l'erreur et d'informer l'utilisateur de la modification manuelle des paramètres du pare-feu.