2017-01-20 25 views
6

将数据发布到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哈希值未被用作认证的一部分离子签名。我现在不得不研究这种行为的根本原因。

+0

尝试在web.config中的appSettings下添加aspnet:MaxJsonDeserializerMembers。检查你的JSON的长度,并把它作为一个值,如

+0

@AliBaig我试着用''没有效果。 – CSL

+0

你有没有试过设置maxRequestLength的大小? – xszaboj

回答

0

https://blogs.msdn.microsoft.com/azureossds/2016/06/15/uploading-large-files-to-azure-web-apps/

检查后最大尺寸为天青。取决于您的配置可能是问题。要么更改配置,要么将邮政大小缩减为更小的区块。

+0

感谢您的建议,但我没有发布太多的数据(少于一兆字节),如果我删除了HMAC身份验证,我可以通过Azure发布更大容量而不会出现问题。这个问题在我的身份验证属性的实现中。我还没有花足够的时间调查出根本原因。 – CSL