前一段时间我使用HttpClient
类实现了一些使用REST Api的代码。
using (var client = new HttpClient() { BaseAddress = new Uri(@"https://thirdparty.com") })
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(...);
var uri = new Uri(@"rest/api/foo", UriKind.Relative);
var content = new StringContent(json.ToString());
using (var response = await client.PostAsync(uri, content))
{
// etc ...
}
}
这个代码似乎对测试和生产环境(每个访问测试/生产uri)都完美无缺。最近,我们开始仅在生产环境中获得HttpRequestException:System.Net.Http.HttpRequestException: Error while copying content to a stream.
这看起来有点奇怪,所以我使用Postman发送相同的消息,它工作得很好。我不确定为什么我们的代码失败了,Postman正在工作。我更改了json数据中的参数(状态从“NY”到“NV”),我们的.NET代码运行正常 - 当然我们不能只发送错误的json数据,所以这不是一个解决方案;这更像是一种观察结果,完全相同的代码在不同的内容下运行良好。
有趣的是,我们可以通过两个代码更改来解决这个问题。首先,Postman能够使用RestSharp
包生成有效的C#代码。或者,我从另一个指向使用HttpVersion 1.0的问题中找到answer:
using (var request = new HttpRequestMessage(HttpMethod.Post, uri))
{
request.Version = HttpVersion.Version10;
request.Content = new StringContent(json.ToString());
using (var response = await client.SendAsync(request))
{
// etc ...
}
}
令人困惑的部分是Postman使用HTTP / 1.1版本。所以,总结一下:
为什么Postman能够使用HTTP / 1.1工作,但HttpClient失败了?这是我们客户的问题(该代码适用于其他美国国家)?这是.NET Framework中的错误吗?从第三方实施/托管REST Api有什么问题吗?
邮差标题:
POST rest/api/foo HTTP/1.1
Host: thirdparty.com
Content-Type: application/json
Authorization: Basic SOME_ENCRYPTED_USER_PASS
Cache-Control: no-cache
Postman-Token: 2fa5b5a0-b5d3-bd4c-40f0-d2b55b60316b
示例Json:
{
"stateCode": "NY",
"packageID": "58330",
"name": "58330-PRI-1",
"documents": [
{
"type": "SPECIAL",
"name": "Sample Document",
"documentID": "3569976"
}
],
"descriptions": [
{
"city": "New York",
"state": "NY"
}
]
}
堆栈跟踪:
AggregateException: One or more errors occured.
HttpRequestException: Error while copying content to a stream.
IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
SocketException: An existing connection was forcibly closed by the remote host.
答案 0 :(得分:1)
由于您可以稍微更改数据并使其成功,我会说您的问题与您的任何代码无关。如果他们的服务器缓存了一个错误值并继续向您发送该值,直到缓存清除,该怎么办?
尝试隐式告诉服务器不要使用缓存值...
using (var client = new HttpClient() { BaseAddress = new Uri(@"https://thirdparty.com") })
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(...);
var uri = new Uri(@"rest/api/foo", UriKind.Relative);
var content = new StringContent(json.ToString());
client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache");
using (var response = await client.PostAsync(uri, content))
{
// etc ...
}
}
并查看您是否获得了有效的回复流。
答案 1 :(得分:0)
您是否在运行HttpClient的计算机上安装了防病毒/防火墙?我过去遇到AVG,Mcafee,Norton和其他人默默阻止请求的问题。找到确切的位置非常棘手,但可能有一个监视端口的选项卡,取消/禁用此功能可能有助于识别问题。如果是这种情况,正确的解决方案是将您的“thirdparty.com”放在相应供应商的白名单上。
可能还值得查看服务器的响应标头吗?你能否将它们添加到你的问题中?只是因为在过去我发现Content-Security-Policy标题阻止了我的一些请求的完成?