CSL*_*CSL 6 c# json azure asp.net-web-api
将数据发布到Azure中托管的Web API服务时,我遇到了一个奇怪的问题,并希望获得任何见解.
我编写了一个非常基本的Web API服务,它有一个控制器,通过Post方法接收List.我使用从a创建的客户端通过控制台应用程序将数据发布到此API HttpClientFactory.
当我在本地调试这一切都运行良好,我已成功发布一个包含100个元素的List,并将其写入我的本地数据库.如果我将本地Web API代码切换为指向我的Azure数据库,它仍然可以正常工作,我可以毫无问题地收到100个元素并写入Azure数据库实例.
当我将API服务部署到我的Azure帐户并挂钩我的控制台应用程序以向其发布数据时 - 它与包含最多45个元素的List完美配合,并且PostAsync等待大约6分钟然后因内部服务器而失败错误.
所以我的问题是为什么服务能够在大约一秒钟内发布43个元素到44个元素失败,但需要6分钟才能完成?
我应该指出我的List包含100个重复的项目,因为我正在生成用于测试的数据,因此集合中的特定元素没有任何错误(或不同).
T是一个简单的类,有大约30个属性,没有子元素,所以我没有发布一个庞大的结构.
我的想法是,这必须是一个大小限制,在我的本地机器上没有生效,但是当我部署到Azure时.我不是Web API专家,所以我不知道从哪里开始寻找.
一些客户端代码(当i <= 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" />
和
<add key="aspnet:MaxJsonDeserializerMembers" value="20000000"/>
我刚刚运行了一个测试,它不适用于44个元素内容长度= 53278
它的最大长度是当我的总元素是43内容长度= 48361时.
注意:我刚刚运行了一些测试,如果我减少了一些字符串属性中的数据长度(从而减少了每个元素的占用空间),我可以发布更多元素.因此它必须是某个地方的消息大小限制!!
更新 - HMAC身份验证
好的,原因始终是您未在问题中记录的最不期望的事情.我在我的API上启用了HMAC身份验证,当我从控制器中删除属性时,我可以发布10000个元素而不会出现问题.一旦启用它,我就会被限制为43.
在客户端上,我生成请求内容的MD5哈希作为头签名的一部分,此过程在Web API服务的HMAC属性中重复.如果我从我的客户端和服务中删除这部分签名,那么我可以发布尽可能多的数据.我在客户端上注释掉的代码如下所示:
//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哈希不会被用作身份验证签名的一部分.
我现在必须研究这种行为的根本原因.
小智 0
https://blogs.msdn.microsoft.com/azureossds/2016/06/15/uploading-large-files-to-azure-web-apps/
检查 Azure 的最大帖子大小。根据您的配置,这可能是问题所在。要么更改配置,要么考虑将帖子大小减小为更小的块。