HTTP POST Возвращает Ошибку:417 “Ожидание не оправдалось”.

StackOverflow https://stackoverflow.com/questions/566437

Вопрос

Когда я пытаюсь ОПУБЛИКОВАТЬ ссылку на 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 header ", ожидающий:100-Продолжить "' для каждого запроса, если вы явно не попросите этого не делать, установив это статическое свойство к ложному:

System.Net.ServicePointManager.Expect100Continue = false;

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

Попробуй это сделать.

Другие советы

Другой способ -

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

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

Такая же ситуация и ошибка также могут возникнуть с прокси-сервером веб-службы SOAP, созданным мастером по умолчанию (не на 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 путем создания производного прокси-класса, который переопределяет 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 это прокси-сервер, который вам выдал мастер добавления веб-ссылок.)


Обновить:Вот impl, который я использую в производстве:

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, и мне пришлось заставить мой прокси-сервер отправлять запросы с использованием HTTP / 1.0, чтобы решить проблему, установив этот аргумент в 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 без необходимости что-либо менять на стороне клиента, надеюсь, это поможет.

Для Powershell это

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

Если вы используете "С помощью HttpClient", и вы не хотите использовать глобальную конфигурацию, чтобы влиять на все ваши программы, которые вы можете использовать:

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

Я, которого ты используешь "Веб - клиент" Я думаю, вы можете попытаться удалить этот заголовок , позвонив:

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

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

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

Подход web.config работает для вызовов служб InfoPath form services к правилам, включающим веб-службу IntApp.

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top