不常见的一个问题,起因是同事使用 .NET Framework 4.6.1 构建的 ASP.NET WebAPI 站点服务的某个 POST 接口需要接收长度接近 7,000,000 的 JSON 字符串,大约 **13.3 MB**。客户端请求成功,服务端也没有报错,但是实际解析出的传输是 null

  1. [POST]
  2. [Route("/api/demo/exec")]
  3. public IHttpActionResult Execute([FromBody] InParam param)
  4. {
  5. // ...
  6. }

问题排查

在看到上述代码后,首先想到的是 [FromBody] 属性,它标识了该入参来自 Http Request Body,那会不会是 ContentType 设置不正确?

检查 ContentType

遂联系其要来构造 HTTP Request 的相关代码,大致如下所示:

  1. private static T Post<T>(string action, object param)
  2. {
  3. var json = JsonConver.SerializeObject(param);
  4. HttpContent httpContent = new StringContent(json);
  5. HttpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  6. HttpContent.Headers.ContentType.CharSet = "utf-8";
  7. //...
  8. }

可以看到,使用 contentType: application/json 来指名使用 JSON 来发送复杂数据应该是完全没问题的。
那么…会不会是长度超出了上限?我们知道 Web 服务出于自身的保护(通常是由 IIS、Nginx 等负载提供),都会限制数据传输的大小,特别是接收的数据。

检查 web.config 中的可配置项

通过上网检索,我们很快可以找到一些相关的配置项:HttpRuntimeSection.MaxRequestLengthaspnet:MaxJsonDeserializerMembers)、maxAllowedContentLength

MaxRequestLength

官方给出的说明是:

MaxRequestLength 属性指定输入流的缓冲阈值的限制。 例如,此限制可用于防止拒绝服务攻击,这些攻击由向服务器发送大型文件的用户造成。 请求的最大大小(以千字节为单位)。 默认大小为 4096 KB (4 MB)。

问题找到了,此配置项的默认大小仅为 4 MB,远远低于我们所需要的 13.3 MB。

MaxJsonDeserializerMembers

官方给出的说明是:

Specifies the limit of the maximum number of items that can be present in any dictionary deserialized by the JavaScriptSerializer type. Default value: 1000

可以看出,此项配置所限制的是反序列化的字段长度。我们要传输的数据模型中所定义的字段远远不足默认配置的 1000 个,因此此项无需修改。

maxAllowedContentLength

官方给出的说明是:

Optional uint attribute. Specifies the maximum length of content in a request, in bytes. The default value is 30,000,000, which is approximately 28.6MB.

也就是说,默认可接受的内容大小为 28.6 MB,满足我们传输的内容大小 13.3 MB,因此此项无需修改。

结论

显然,按目前我们的需求,只需要配置 MaxRequestLength 一项即可。

解决方案

打开 web.config 文件,添加或修改以下配置项:

  1. <system.web>
  2. <!-- targetFramework 属性是你的 .NET Framework 版本-->
  3. <!-- maxRequestLength 请按实际需求设置(KB),此处 2147483647 为可设置的最大值-->
  4. <httpRuntime targetFramework="4.6.1" maxRequestLength="2147483647" />
  5. </system.web>

参考资料

  1. 解决.NETMVC(ajax)Json请求太大,无法反序列化(The JSON request was too large to be deserialized)问题
  2. 关于 asp.net Web Api 请求内容过大解决记录。