c# - example - HTTP POST devuelve error: 417 "Error de expectativa".
webrequest post c# json (9)
Cuando intento realizar un POST a una URL, se produce la siguiente excepción:
El servidor remoto devolvió un error: (417) Error de expectativa.
Aquí hay un código de ejemplo:
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.
El uso de un par de HttpWebRequest/HttpWebResponse
o un HttpClient
no hace una diferencia.
¿Qué está causando esta excepción?
¿El formulario que está intentando emular tiene dos campos, nombre de usuario y contraseña?
Si es así, esta línea:
postData.Add("username", "password");
no es correcto.
necesitarías dos líneas como:
postData.Add("username", "Moose");
postData.Add("password", "NotMoosespasswordreally");
Editar:
De acuerdo, ya que ese no es el problema, una forma de abordar esto es usar algo como Fiddler o Wireshark para ver con éxito lo que se envía al servidor web desde el navegador, y luego compararlo con lo que se envía desde su código. Si va a un puerto 80 normal desde .Net, Fiddler seguirá capturando este tráfico.
Probablemente haya algún otro campo oculto en el formulario que el servidor web espera que no esté enviando.
De otra manera -
Agregue estas líneas a su sección de configuración del archivo de configuración de la aplicación:
<system.net>
<settings>
<servicePointManager expect100Continue="false" />
</settings>
</system.net>
El enfoque web.config funciona para las llamadas de servicios de formulario de InfoPath a las reglas habilitadas para el servicio web de IntApp.
<system.net>
<defaultProxy />
<settings> <!-- 20130323 bchauvin -->
<servicePointManager expect100Continue="false" />
</settings>
</system.net>
En mi situación, este error parece ocurrir solo si la computadora de mi cliente tiene una estricta política de firewall, lo que impide que mi programa se comunique con el servicio web.
Por lo tanto, la única solución que pude encontrar es detectar el error e informar al usuario sobre cómo cambiar la configuración del firewall manualmente.
Esta misma situación y error también pueden surgir con un asistente de servicio web SOAP generado por el asistente predeterminado (no al 100% si este también es el caso en la pila de WCF System.ServiceModel
) cuando está en tiempo de ejecución:
- la máquina del usuario final está configurada (en la configuración de Internet) para usar un proxy que no entiende HTTP 1.1
- el cliente termina enviando algo que un proxy HTTP 1.0 no entiende (generalmente un encabezado
Expect
como parte de unaPOST
HTTPPOST
oPUT
debido a una convención de protocolo estándar de enviar la solicitud en dos partes, como se explica en las Notas aquí )
... rindiendo un 417.
Como se explica en las otras respuestas, si el problema específico con el que se encuentra es que el encabezado Expect
está causando el problema, entonces ese problema específico puede solucionarse realizando un apagado relativamente global de la transmisión PUT / POST de dos partes a través del System.Net.ServicePointManager.Expect100Continue
.
Sin embargo, esto no soluciona el problema subyacente completo: la pila puede seguir utilizando elementos específicos de HTTP 1.1, como KeepAlives, etc. (aunque en muchos casos las otras respuestas sí cubren los casos principales).
Sin embargo, el problema real es que el código generado automáticamente asume que está bien ir a ciegas utilizando las instalaciones de HTTP 1.1, ya que todos lo entienden. Para detener esta suposición para un proxy de servicio web específico, se puede cambiar anular el valor predeterminado subyacente HttpWebRequest.ProtocolVersion
del valor predeterminado de 1.1 al crear una clase Proxy derivada que invalida el reemplazo protected override WebRequest GetWebRequest(Uri uri)
como se muestra en esta publicación :
public class MyNotAssumingHttp11ProxiesAndServersProxy : MyWS
{
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
request.ProtocolVersion = HttpVersion.Version10;
return request;
}
}
(donde MyWS
es el proxy que el asistente para agregar referencias web te escupió).
ACTUALIZACIÓN: Aquí hay un impl que estoy usando en producción:
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 };
}
}
Para Powershell es
[System.Net.ServicePointManager]::Expect100Continue = $false
Si está utilizando " HttpClient ", y no quiere usar la configuración global para afectar todo lo que programa puede usar:
HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClient.DefaultRequestHeaders.ExpectContinue = false;
Si está utilizando " WebClient ", creo que puede intentar eliminar este encabezado llamando a:
var client = new WebClient();
client.Headers.Remove(HttpRequestHeader.Expect);
Solución desde el lado del proxy, enfrenté algunos problemas en el proceso de intercambio de SSL y tuve que forzar a mi servidor proxy a enviar solicitudes usando HTTP / 1.0 para resolver el problema configurando este argumento en el httpd.conf SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
después de eso, enfrenté el error 417 porque la aplicación de mis clientes estaba usando HTTP / 1.1 y el proxy se vio obligado a usar HTTP / 1.0, el problema se resolvió al configurar este parámetro en httpd.conf en el lado del proxy RequestHeader unset Expect early
sin la necesidad de cambiar nada en el lado del cliente, espero que esto ayude.
System.Net.HttpWebRequest agrega el encabezado ''Encabezado HTTP "Esperar: 100-Continuar" a cada solicitud a menos que usted lo pida explícitamente al no establecer esta propiedad estática en falso:
System.Net.ServicePointManager.Expect100Continue = false;
Algunos servidores se ahogan en ese encabezado y devuelven el error 417 que está viendo.
Dale un tiro.