C# HTTP POST 返回错误:417“期望失败”。

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/566437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 08:26:24  来源:igfitidea点击:

HTTP POST Returns Error: 417 "Expectation Failed."

c#.nethttphttp-postwebclient

提问by Saeb Amini

When I try to POST to a URL it results in the following exception:

当我尝试 POST 到一个 URL 时,它会导致以下异常:

The remote server returned an error: (417) Expectation Failed.

远程服务器返回错误:(417) 预期失败。

Here's a sample code:

这是一个示例代码:

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.

Using an HttpWebRequest/HttpWebResponsepair or an HttpClientdoesn't make a difference.

使用一HttpWebRequest/HttpWebResponse对或一个HttpClient没有区别。

What's causing this exception?

是什么导致了这个异常?

采纳答案by xcud

System.Net.HttpWebRequest adds the header 'HTTP header "Expect: 100-Continue"' to every request unless you explicitly ask it not to by setting this static propertyto false:

System.Net.HttpWebRequest 向每个请求添加标头“HTTP 标头“Expect: 100-Continue””,除非您通过将此静态属性设置为 false明确要求不要这样做:

System.Net.ServicePointManager.Expect100Continue = false;

Some servers choke on that header and send back the 417 error you're seeing.

某些服务器在该标头上阻塞并发回您看到的 417 错误。

Give that a shot.

试一试。

回答by Moose

Does the form you are trying to emulate have two fields, username and password?

您尝试模拟的表单是否有两个字段,用户名和密码?

If so, this line:

如果是这样,这一行:

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

is not correct.

是不正确的。

you would need two lines like:

你需要两行,如:

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

Edit:

编辑:

Okay, since that is not the problem, one way to tackle this is to use something like Fiddler or Wireshark to watch what is being sent to the web server from the browser successfully, then compare that to what is being sent from your code. If you are going to a normal port 80 from .Net, Fiddler will still capture this traffic.

好的,既然这不是问题,解决这个问题的一种方法是使用 Fiddler 或 Wireshark 之类的东西来观察从浏览器成功发送到 Web 服务器的内容,然后将其与从您的代码发送的内容进行比较。如果您要从 .Net 访问普通端口 80,Fiddler 仍会捕获此流量。

There is probably some other hidden field on the form that the web server is expecting that you are not sending.

表单上可能还有一些其他隐藏字段,Web 服务器希望您不会发送这些字段。

回答by Engin Ard??

Another way -

其它的办法 -

Add these lines to your application config file configuration section:

将这些行添加到您的应用程序配置文件配置部分:

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

回答by Ruben Bartelink

This same situation and error can also arise with a default wizard generated SOAP Web Service proxy (not 100% if this is also the case on the WCF System.ServiceModelstack) when at runtime:

System.ServiceModel在运行时,默认向导生成的 SOAP Web 服务代理(如果 WCF堆栈也是这种情况,则不是 100%)也会出现相同的情况和错误:

  • the end user machine is configured (in the Internet Settings) to use a proxy that does not understand HTTP 1.1
  • the client ends up sending something that a HTTP 1.0 proxy doesnt understand (commonly an Expectheader as part of a HTTP POSTor PUTrequest due to a standard protocol convention of sending the request in two parts as covered in the Remarks here)
  • 最终用户机器被配置(在 Internet 设置中)使用不理解 HTTP 1.1 的代理
  • 客户端最终会发送 HTTP 1.0 代理无法理解的内容(通常将Expect标头作为 HTTPPOSTPUT请求的一部分,因为标准协议约定将请求分为两部分发送,如此处的备注中所述

... yielding a 417.

...产生417。

As covered in the other answers, if the specific issue you run into is that the Expectheader is causing the problem, then that specific problem can be routed around by doing a relatively global switching off of the two-part PUT/POST transmission via System.Net.ServicePointManager.Expect100Continue.

正如其他答案中所述,如果您遇到的具体问题是Expect标头导致问题,那么可以通过System.Net.ServicePointManager.Expect100Continue.

However this does not fix the complete underlying problem - the stack may still be using HTTP 1.1 specific things such as KeepAlives etc. (though in many cases the other answers do cover the main cases.)

然而,这并不能解决完整的潜在问题 - 堆栈可能仍在使用 HTTP 1.1 特定的东西,例如 KeepAlives 等(尽管在许多情况下其他答案确实涵盖了主要情况。)

The actual problem is however that the autogenerated code assumes that it's OK to go blindly using HTTP 1.1 facilities as everyone understands this. To stop this assumption for a specific Web Service proxy, one can change override the default underlying HttpWebRequest.ProtocolVersionfrom the default of 1.1by creating a derived Proxy class which overrides protected override WebRequest GetWebRequest(Uri uri)as shown in this post:-

然而,实际的问题是自动生成的代码假设盲目使用 HTTP 1.1 设施是可以的,因为每个人都理解这一点。要停止对特定 Web 服务代理的这种假设,可以通过创建一个派生的 Proxy 类来更改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;
    }
}

(where MyWSis the proxy the Add Web Reference wizard spat out at you.)

MyWS添加 Web 引用向导向您吐出的代理在哪里。)



UPDATE: Here's an impl I'm using in production:

更新:这是我在生产中使用的一个实现:

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

回答by BobC

The web.config approach works for InfoPath form services calls to IntApp web service enabled rules.

web.config 方法适用于对 IntApp Web 服务启用规则的 InfoPath 表单服务调用。

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>

回答by Hytham

Solution from proxy side, I faced some problems in the SSL handshake process and I had to force my proxy server to send requests using HTTP/1.0 to solve the problem by setting this argument in the httpd.conf SetEnv force-proxy-request-1.0 1SetEnv proxy-nokeepalive 1after that I faced the 417 error as my clients application was using HTTP/1.1 and the proxy was forced to use HTTP/1.0, the problem was solved by setting this parameter in the httpd.conf on the proxy side RequestHeader unset Expect earlywithout the need to change anything in the client side, hope this helps.

代理端的解决方案,我在 SSL 握手过程中遇到了一些问题,我不得不强制我的代理服务器使用 HTTP/1.0 发送请求,通过在 httpd.conf 中设置这个参数来解决问题,SetEnv force-proxy-request-1.0 1SetEnv proxy-nokeepalive 1之后我遇到了 417 错误我的客户端应用程序使用 HTTP/1.1 并且代理被迫使用 HTTP/1.0,通过在代理端的 httpd.conf 中设置此参数解决了问题RequestHeader unset Expect early,无需在客户端更改任何内容,希望这有帮助.

回答by Emre Can Serteli

In my situation, this error seems to occur only if my client's computer has a strict firewall policy, which prevents my program from communicating with the web service.

在我的情况下,这个错误似乎只有在我客户的计算机有严格的防火墙策略时才会发生,这会阻止我的程序与 Web 服务进行通信。

So only solution I could find is to catch the error and inform user about changing the firewall settings manually.

所以我能找到的唯一解决方案是捕获错误并通知用户手动更改防火墙设置。

回答by Aviram Fireberger

If you are using "HttpClient", and you don't want to use global configuration to affect all you program you can use:

如果您正在使用“ HttpClient”,并且您不想使用全局配置来影响您可以使用的所有程序:

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

I you are using "WebClient" I think you can try to remove this header by calling:

如果您使用的是“ WebClient”,我想您可以尝试通过调用以下方法删除此标头:

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

回答by TNT

For Powershell it is

对于 Powershell,它是

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