Pergunta

Quando tento POST a uma URL que resulta na seguinte exceção:

O servidor remoto retornou um erro: (417) Expectativa falhada.

Aqui está um código de exemplo:

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.

Usando um par HttpWebRequest/HttpWebResponse ou um HttpClient não fazer a diferença.

O que está causando essa exceção?

Foi útil?

Solução

System.Net.HttpWebRequest adiciona o cabeçalho 'cabeçalho HTTP 'esperado: 100-Continue'' para cada pedido a menos que você pedir explicitamente não definindo esta propriedade estática para false:

System.Net.ServicePointManager.Expect100Continue = false;

Alguns servidores engasgar com esse cabeçalho e enviar de volta o 417 erro que você está vendo.

dar esse um tiro.

Outras dicas

Outra forma -

Adicione estas linhas ao seu seção de configuração do arquivo de configuração do aplicativo:

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

Esta mesma situação e erro também pode surgir com um assistente padrão gerado procuração SABÃO Web Service (não 100%, se este é também o caso na pilha WCF System.ServiceModel), quando em tempo de execução:

  • máquina do usuário final está configurado (nas configurações de Internet) para usar um proxy que não entende HTTP 1.1
  • as extremidades do cliente enviando algo que does not proxy HTTP 1.0 entender (comumente um cabeçalho Expect como parte de uma solicitação HTTP POST ou PUT devido a uma convenção do protocolo padrão de envio do pedido em duas partes como coberta nas Observações aqui )

... produzindo uma 417.

Como cobertos em outras respostas, se o problema específico que você correr em é que o cabeçalho Expect está causando o problema, então esse problema específico podem ser encaminhadas ao redor, fazendo uma comutação relativamente mundial fora da bipartido PUT / POST transmissão via System.Net.ServicePointManager.Expect100Continue .

No entanto isso não corrigir o problema subjacente completa - a pilha pode ainda estar usando HTTP 1.1 coisas específicas, como KeepAlives etc. (. Embora em muitos casos as outras respostas não cobrem os principais casos)

O problema real é, porém, que o código gerado automaticamente assume que não há problema em ir às cegas utilizando HTTP 1.1 facilidades que todos entendam isso. Para parar esse pressuposto para um determinado proxy de serviço Web, pode-se alterar substituir o padrão subjacente HttpWebRequest.ProtocolVersion do padrão de 1.1 criando uma classe Proxy derivada que substitui protected override WebRequest GetWebRequest(Uri uri) como mostrado neste post : -

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

(onde MyWS é o proxy o Assistente para adicionar referência Web cuspiu em você.)


UPDATE: Aqui está um impl que estou usando na produção:

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 };
    }
}

O formulário que você está tentando emular tem dois campos, nome de usuário e senha?

Se assim for, esta linha:

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

não é correto.

você precisaria de duas linhas como:

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

Editar:

Ok, uma vez que não é o problema, uma maneira de lidar com isso é usar algo como Fiddler ou Wireshark para ver o que está sendo enviado para o servidor web a partir do navegador com sucesso, então comparar com o que está sendo enviada do seu código. Se você estiver indo para uma porta normal de 80 de .Net, Fiddler ainda irá capturar este tráfego.

Há provavelmente algum outro campo oculto no formulário que o servidor web está esperando que você não está enviando.

Solução de um lado proxy, eu enfrentei alguns problemas no processo de SSL aperto de mão e eu tive que forçar o meu servidor proxy para enviar solicitações usando HTTP / 1.0 para resolver o problema, definindo este argumento no httpd.conf SetEnv force-proxy-request-1.0 1 SetEnv proxy-nokeepalive 1 depois que eu enfrentei o erro 417, como a minha candidatura clientes estava usando HTTP / 1.1 e o proxy foi forçado a usar HTTP / 1.0, o problema foi resolvido definindo este parâmetro no httpd.conf no RequestHeader unset Expect early lado do proxy sem a necessidade de mudar nada no lado do cliente, espero que isso ajude.

Para PowerShell é

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

Se você estiver usando " HttpClient ", e você não quer usar a configuração global para afetar tudo o que você programa você pode usar:

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

Eu você está usando " WebClient " Eu acho que você pode tentar remover este cabeçalho chamando:

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

Na minha situação, este erro parece ocorrer apenas se o computador do meu cliente tem uma rigorosa política de firewall, o que impede o meu programa de comunicar com o serviço web.

Assim única solução que eu poderia encontrar é pegar o erro e informar usuário sobre como alterar as configurações de firewall manualmente.

A abordagem web.config trabalha para InfoPath Form Services chamadas para IntApp serviço web habilitado regras.

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top