HTTP POST возвращает ошибку: 417 «Ожидание не выполнено».

Когда я пытаюсь отправить POST на URL-адрес, это приводит к следующему исключению:

Удаленный сервер ответил на ошибку: (417) Ошибка ожидания.

Вот пример кода:

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. 

Использование HttpWebRequest/HttpWebResponse или HttpClient не имеет значения.

Что вызывает это исключение?

System.Net.HttpWebRequest добавляет заголовок «HTTP-заголовок» Expect: 100-Continue «» для каждого запроса, если вы явно не попросите его не устанавливать это значение static в значение false:

 System.Net.ServicePointManager.Expect100Continue = false; 

Некоторые серверы дросселируют этот заголовок и отправляют обратно 417 ошибку, которую вы видите.

Дайте это выстрел.

Другой путь –

Добавьте эти строки в раздел конфигурации файла конфигурации приложения:

      

Такая же ситуация и ошибка также могут возникнуть с созданным по умолчанию мастером прокси-сервера SOAP Web Service (не на 100%, если это также имеет место в стеке WCF System.ServiceModel ), когда во время выполнения:

  • машина конечного пользователя настроена (в настройках Интернета) для использования прокси-сервера, который не понимает HTTP 1.1
  • клиент заканчивает отправку того, что прокси-сервер HTTP 1.0 не понимает (обычно заголовок Expect как часть запроса HTTP POST или PUT из-за стандартного соглашения о протоколе отправки запроса в двух частях, как описано в примечаниях здесь )

… дает 417.

Как описано в других ответах, если конкретная проблема, с которой вы столкнулись, заключается в том, что заголовок Expect вызывает проблему, тогда эту конкретную проблему можно перенаправить, выполняя относительно глобальное отключение двухчастной передачи PUT / POST через System.Net.ServicePointManager.Expect100Continue .

Однако это не устраняет полную основную проблему – стек может по-прежнему использовать определенные HTTP 1.1 такие вещи, как KeepAlives и т. Д. (Хотя во многих случаях другие ответы охватывают основные случаи).

Однако актуальной проблемой является то, что автогенерированный код предполагает, что все в порядке, чтобы слепо использовать HTTP 1.1, поскольку все это понимают. Чтобы остановить это предположение для определенного прокси-сервера веб-службы, можно изменить переопределить по умолчанию HttpWebRequest.ProtocolVersion по умолчанию 1.1 , создав производный class Proxy, который переопределяет protected override WebRequest GetWebRequest(Uri uri) как показано в этом сообщении :

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

(где MyWS – это прокси-сервер, который MyWS на вас мастер добавления веб-ссылок).


UPDATE: Вот что я использую в производстве:

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

У формы, которую вы пытаетесь эмулировать, есть два поля, имя пользователя и пароль?

Если это так, эта строка:

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

не является правильным.

вам понадобятся две строки:

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

Редактировать:

Хорошо, так как это не проблема, один из способов решения этой проблемы – использовать что-то вроде Fiddler или Wireshark, чтобы наблюдать за тем, что отправляется на веб-сервер из браузера, и сравнить его с тем, что отправляется из вашего кода. Если вы перейдете на обычный порт 80 из .Net, Fiddler все равно захватит этот трафик.

Вероятно, есть какое-то другое скрытое поле в форме, которую веб-сервер ожидает, что вы не отправляете.

Решение со стороны прокси-сервера, я столкнулся с некоторыми проблемами в процессе установления SSL-SSL, и мне пришлось заставить свой прокси-сервер отправлять запросы с использованием HTTP / 1.0 для решения проблемы, установив этот аргумент в SetEnv force-proxy-request-1.0 1 httpd.conf SetEnv force-proxy-request-1.0 1 SetEnv proxy-nokeepalive 1 после этого я столкнулся с ошибкой 417, поскольку приложение моих клиентов использовало HTTP / 1.1, а прокси-сервер был вынужден использовать HTTP / 1.0, проблема была решена путем установки этого параметра в httpd.conf на прокси-стороне RequestHeader unset Expect early не изменяя ничего на стороне клиента, надеюсь, что это поможет.

Если вы используете « HttpClient », и вы не хотите использовать глобальную конфигурацию для воздействия на всю вашу программу, которую вы можете использовать:

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

Я использую « WebClient ». Я думаю, вы можете попытаться удалить этот заголовок, позвонив:

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

Для Powershell это

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

Подход web.config работает для вызовов форм формы InfoPath для правил, поддерживаемых веб-сервисами IntApp.

         

В моей ситуации эта ошибка возникает, только если компьютер моего клиента имеет строгую политику брандмауэра, что мешает моей программе общаться с веб-службой.

Поэтому единственным решением, которое я смог найти, является обнаружение ошибки и информирование пользователя об изменении настроек брандмауэра вручную.

  • Установите тайм-аут для webClient.DownloadFile ()
  • Загрузка файлов на файловый сервер с использованием classа webclient
  • Загрузите и загрузите двоичный файл на / из FTP-сервера в C # /. NET
  • Как я могу заставить WebClient использовать Cookies?
  • POSTing JSON для URL через WebClient в C #
  • Как я могу программным образом удалить 2 ограничения соединения в WebClient
  • C # WebClient отключить кеш
  • ASP.NET-controller: asynchronous модуль или обработчик завершен, пока асинхронная операция все еще находится на рассмотрении
  • Как заполнить формы и отправить с помощью Webclient в C #
  • C # - Как сделать HTTP-вызов
  • C # webclient и прокси-сервер
  • Давайте будем гением компьютера.