将数据发布到Azure托管的Web API服务时遇到了一个奇怪的问题,并且希望得到任何见解。发布JSON数据WebAPI
我写了一个非常基本的Web API服务,它有一个通过Post方法接收List的控制器。我通过控制台应用程序使用从HttpClientFactory
创建的客户端将数据发布到此API。
当我在本地调试这一切都工作得很好,我成功地发布了一个包含100个元素的列表,并将其写入我的本地数据库。如果我将本地Web API代码切换为指向我的Azure数据库,它仍然可以正常运行,并且我可以毫无问题地接收100个元素并写入Azure数据库实例。
当我将API服务部署到我的Azure帐户并挂接我的控制台应用程序以向其发布数据时 - 它完全适用于包含多达45个元素的列表,并且PostAsync等待大约6分钟,然后失败与内部服务器错误。
所以我的问题是为什么服务从能够在一秒钟内发布43个元素失败44个元素,但需要6分钟这样做呢?
我应该指出我的List包含100个重复的项目,因为我正在生成测试数据,所以没有任何错误(或不同)与该集合中的特定元素。
T是简单的类,有大约30个属性,没有子元素,所以我没有发布一个庞大的结构。
我的想法是这应该是一个大小限制,在我的本地计算机上没有生效,但是当我部署到Azure时。我不是一个Web API专家,所以我不确定从哪里开始寻找。
某些客户端代码(完美的作品时,我< = 43):
List<Foo> results = new List<Foo>();
for (int i = 1; i < 100; i++)
{
results.Add(new Foo() { // Populated with data - removed for brevity });
}
StringContent content = new StringContent(JsonConvert.SerializeObject(results), Encoding.UTF8, "application/json");
HttpResponseMessage postDataResponse = await postClient.PostAsync(myWebApiServiceURL, content);
控制器的方法:
[HttpPost]
public List<Foo>Post([FromBody]List<Foo> value)
{
return value;
}
web.config设置我已经试过了没有效果:
<httpRuntime targetFramework="4.6.1" maxRequestLength="200000000" requestLengthDiskThreshold="16384" />
and
<add key="aspnet:MaxJsonDeserializerMembers" value="20000000"/>
我刚跑了测试,它不与44种元素内容长度工作= 53278
它的工作原理是在我的时候总元素43的内容长度的最大长度= 48361.
注意:我刚刚运行了一些更多的测试,如果我在某些字符串属性中减少数据长度(从而减少每个元素的占用空间),我可以发布更多元素。因此它必须是某个地方的消息大小限制!
更新 - HMAC认证
OK事业始终是你不要在提问资料最少意料之中的事情。我在我的API上启用了HMAC身份验证,当我从控制器中删除属性时,我可以发布10000个元素而没有问题。只要我启用它,我就被限制回到43.
在客户端上,我生成请求内容的MD5哈希作为头部签名的一部分,此过程正在Web上的HMAC属性中重复API服务。如果我从客户和服务中删除这部分签名,那么我可以发布尽可能多的数据。我已在客户端上注释掉的代码如下所示:
//Checking if the request contains body, usually will be null with HTTP GET and DELETE
if (request.Content != null)
{
byte[] content = await request.Content.ReadAsByteArrayAsync();
MD5 md5 = MD5.Create();
//Hashing the request body, any change in request body will result in different hash, we'll incure message integrity
byte[] requestContentHash = md5.ComputeHash(content);
requestContentBase64String = Convert.ToBase64String(requestContentHash);
}
我已经在服务注释掉的代码如下:
byte[] hash = await ComputeHash(req.Content);
if (hash != null)
{
requestContentBase64String = Convert.ToBase64String(hash);
}
ComputeHash
功能:
private static async Task<byte[]> ComputeHash(HttpContent httpContent)
{
using (MD5 md5 = MD5.Create())
{
byte[] hash = null;
var content = await httpContent.ReadAsByteArrayAsync();
if (content.Length != 0)
{
hash = md5.ComputeHash(content);
}
return hash;
}
}
所以上面的代码被注释掉requestContentBase64String
在客户端和服务器上都是空字符串,因此内容的MD5哈希值未被用作认证的一部分离子签名。我现在不得不研究这种行为的根本原因。
尝试在web.config中的appSettings下添加aspnet:MaxJsonDeserializerMembers。检查你的JSON的长度,并把它作为一个值,如 –
@AliBaig我试着用' '没有效果。 –
CSL
你有没有试过设置maxRequestLength的大小? – xszaboj