Domanda

Quando si tenta di POST a un URL il risultato e 'la seguente eccezione:

  

Il server remoto ha restituito un errore:   (417) Expectation Failed.

Ecco un esempio di codice:

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'utilizzo di un paio HttpWebRequest/HttpWebResponse o un HttpClient non fare la differenza.

Che cosa sta causando questa eccezione?

È stato utile?

Soluzione

System.Net.HttpWebRequest aggiunge l'intestazione 'intestazione HTTP 'Expect: 100-Continue'' ad ogni richiesta a meno che non si chiede esplicitamente di non impostando questa proprietà statica su false:

System.Net.ServicePointManager.Expect100Continue = false;

Alcuni server soffocare su quel colpo di testa e rimandano l'errore 417 che stai vedendo.

Dare che un colpo.

Altri suggerimenti

Un altro modo -

Aggiungere queste righe al sezione di configurazione file di configurazione dell'applicazione:

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

Questa stessa situazione e l'errore può anche sorgere con un sapone proxy Web Servizio procedura guidata di default generato (non al 100%, se questo è anche il caso sullo stack System.ServiceModel WCF), quando in fase di esecuzione:

  • la macchina dell'utente finale è configurata (nelle impostazioni di Internet) per utilizzare un proxy che non capisce HTTP 1.1
  • il cliente finisce per l'invio di qualcosa che un proxy HTTP 1.0 non capisce (comunemente un'intestazione Expect come parte di un POST HTTP o richiesta PUT a causa di una convenzione protocollo standard di invio della richiesta in due parti come coperto nelle osservazioni qui )

... ottenendo un 417.

Come coperto in altre risposte, se il problema specifico si esegue in è che l'intestazione Expect è la causa del problema, quindi che problema specifico può essere instradato in giro facendo una commutazione relativamente globale fuori della due parti PUT / POST trasmissione tramite System.Net.ServicePointManager.Expect100Continue .

Tuttavia, questo non risolve il problema di fondo completa - lo stack può essere ancora utilizzando il protocollo HTTP 1.1 cose specifiche come ad esempio keepalives ecc (. Anche se in molti casi, le altre risposte coprono i casi principali)

Il vero problema è però che il codice generato automaticamente dal presupposto che è OK per andare alla cieca usando HTTP 1.1 strutture come tutti capiscono questo. Per fermare questa ipotesi per una specifica delega Web Service, si può cambiare ignorare l'impostazione predefinita sottostante HttpWebRequest.ProtocolVersion dal default di 1.1 con la creazione di una classe proxy derivata che prevale protected override WebRequest GetWebRequest(Uri uri) come mostrato in questo post : -

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

(dove MyWS è il proxy la procedura guidata di riferimento Web Add sputato fuori a voi.)


UPDATE: Ecco un impl sto usando nella produzione:

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

Fa la forma che si sta tentando di emulare avere due campi, username e password?

Se è così, questa linea:

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

non è corretto.

si avrebbe bisogno di due linee come:

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

Modifica:

D'accordo, dal momento che non è il problema, un modo per affrontare questo è quello di usare qualcosa come Fiddler o Wireshark per guardare ciò che viene inviato al server web dal browser con successo, quindi confrontare che a ciò che viene inviato dal tuo codice. Se avete intenzione di una porta normale 80 da Net, Fiddler sarà ancora catturare questo traffico.

C'è probabilmente qualche altro campo nascosto sulla forma che il server Web si aspetta che non si sta inviando.

Soluzione da un lato proxy, ho affrontato alcuni problemi nel processo di handshake SSL e ho dovuto forzare il server proxy per inviare le richieste tramite HTTP / 1.0 per risolvere il problema impostando questo argomento nella SetEnv force-proxy-request-1.0 1 httpd.conf SetEnv proxy-nokeepalive 1 dopo che ho affrontato l'errore 417 come la mia applicazione client stava usando HTTP / 1.1 e il proxy è stato costretto a utilizzare HTTP / 1.0, il problema è stato risolto con l'impostazione di questo parametro nel httpd.conf sul lato RequestHeader unset Expect early proxy senza la necessità di cambiare qualcosa nel lato client, speriamo che questo aiuta.

Per PowerShell è

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

Se si sta usando " HttpClient ", e non si desidera utilizzare la configurazione globale per influenzare tutto il programma è possibile utilizzare:

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

I si sta utilizzando " WebClient " Penso che si può cercare di rimuovere questa intestazione chiamando:

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

Nella mia situazione, questo errore sembra verificarsi solo se il computer del mio cliente ha una politica rigorosa firewall, che impedisce il mio programma di comunicare con il servizio web.

Così unica soluzione che ho trovato è quello di catturare l'errore e informare all'utente di cambiare le impostazioni del firewall manualmente.

L'approccio web.config lavora per i servizi di modulo di InfoPath chiamate a IntApp servizi Web regole abilitati.

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top