217

当我尝试 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并没有什么不同。

是什么导致了这个异常?

4

10 回答 10

481

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

System.Net.ServicePointManager.Expect100Continue = false;

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

试一试。

于 2009-02-19T19:45:45.263 回答
115

其他方式 -

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

<system.net>
    <settings>
        <servicePointManager expect100Continue="false" />
    </settings>
</system.net>
于 2011-09-09T07:34:17.663 回答
31

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

  • 最终用户机器被配置(在 Internet 设置中)使用不理解 HTTP 1.1 的代理
  • 客户端最终发送了 HTTP 1.0 代理不理解的内容(通常是Expect作为 HTTPPOSTPUT请求的一部分的标头,因为标准协议约定分两部分发送请求,如此处的备注中所述

... 产生 417。

如其他答案所述,如果您遇到的特定问题是Expect标头导致问题,则可以通过相对全局关闭两部分 PUT/POST 传输来解决该特定问题System.Net.ServicePointManager.Expect100Continue

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

然而,实际问题是自动生成的代码假定可以盲目地使用 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;
    }
}

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


更新:这是我在生产中使用的一个 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 };
    }
}
于 2012-06-06T14:14:36.543 回答
5

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

如果是这样,这一行:

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

是不正确的。

你需要两行,比如:

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

编辑:

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

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

于 2009-02-19T18:01:21.597 回答
4

代理方面的解决方案,我在 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无需在客户端更改任何内容,希望这会有所帮助.

于 2013-05-28T06:19:22.790 回答
3

对于 Powershell 它是

[System.Net.ServicePointManager]::Expect100Continue = $false
于 2018-03-01T18:03:50.253 回答
2

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

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

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

 var client = new WebClient();
 client.Headers.Remove(HttpRequestHeader.Expect);
于 2017-07-11T12:45:17.120 回答
0

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

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

于 2015-07-21T07:51:39.567 回答
0

检查您的网络连接是否未重定向。

当我使用错误的 wifi 并且任何网络请求都重定向到公司登录页面时,我遇到了这个问题。

于 2020-11-06T01:04:16.050 回答
-1

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

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>
于 2013-03-24T22:58:47.833 回答