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 标头”期望:100-Continue"' 处理每个请求,除非您通过设置明确要求它不要这样做 这个静态属性 为假:
System.Net.ServicePointManager.Expect100Continue = false;
有些服务器会因该标头而阻塞并发送回您所看到的 417 错误。
试一试。
其他提示
另一种方式 -
这些行添加到你的应用程序的配置文件的配置部分:
<system.net>
<settings>
<servicePointManager expect100Continue="false" />
</settings>
</system.net>
默认向导生成的 SOAP Web 服务代理也会出现同样的情况和错误(如果 WCF 上也是这种情况,则不是 100%) System.ServiceModel
堆栈)在运行时:
- 最终用户计算机配置为(在 Internet 设置中)使用不理解 HTTP 1.1 的代理
- 客户端最终发送了 HTTP 1.0 代理无法理解的内容(通常是
Expect
标头作为 HTTP 的一部分POST
或者PUT
由于分两部分发送请求的标准协议约定而产生的请求 如此处的备注所述)
...产生 417。
正如其他答案中所述,如果您遇到的具体问题是 Expect
header 导致了问题,那么可以通过相对全局地关闭两部分 PUT/POST 传输来解决该特定问题 System.Net.ServicePointManager.Expect100Continue
.
然而,这并不能解决完整的底层问题 - 堆栈可能仍在使用 HTTP 1.1 特定的东西,例如 KeepAlives 等。(尽管在很多情况下,其他答案确实涵盖了主要情况。)
然而,实际的问题是,自动生成的代码假定盲目使用 HTTP 1.1 设施是可以的,因为每个人都明白这一点。要停止对特定 Web 服务代理的这种假设,可以更改覆盖默认底层 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 引用”向导向您吐出的代理。)
更新:这是我在生产中使用的一个实现:
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");
编辑:
好了,因为这是没有问题的,解决方法之一就是使用类似小提琴手或者Wireshark来观看的内容被发送到来自浏览器的Web服务器成功,那么比较,为正在从发送你的码。如果你要一个正常的端口80从.net,提琴手仍会捕捉这些流量。
有可能是一些其他的隐藏字段Web服务器期待您不发送。
在表格上从代理侧解决方案,我面临的SSL握手过程中的一些问题,我不得不强迫我的代理服务器使用发送请求HTTP / 1.0通过在httpd.conf SetEnv force-proxy-request-1.0 1
设置此参数来解决这个问题
之后,我所面临的417错误是我的客户应用SetEnv proxy-nokeepalive 1
使用了HTTP / 1.1和代理被迫通过设置在代理侧RequestHeader unset Expect early
在httpd.conf这个参数,而无需使用HTTP / 1.0,问题解决了更改客户端的什么,希望这有助于。
有关Powershell的是
[System.Net.ServicePointManager]::Expect100Continue = $false
如果您正在使用“的HttpClient ”,你不希望使用全局配置影响到所有你程序,你可以使用:
HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClient.DefaultRequestHeaders.ExpectContinue = false;
我使用的是“ Web客户端”我觉得你可以尝试通过调用删除此标题:
var client = new WebClient();
client.Headers.Remove(HttpRequestHeader.Expect);
在我的情况,这个错误似乎只有当我的客户端的计算机有严格的防火墙策略,以防止我的程序从与Web服务通信发生。
因此,只有我能找到的解决方案是捕获错误并通知用户有关手动更改防火墙设置。
在web.config中方法适用于InfoPath表单服务调用IntApp Web服务启用的规则。
<system.net>
<defaultProxy />
<settings> <!-- 20130323 bchauvin -->
<servicePointManager expect100Continue="false" />
</settings>
</system.net>