【问题标题】:AJAX POST Data to MVC Controller in ASP.NET Core Always Null When Passing An Object Array Over a Certain Length传递超过一定长度的对象数组时,AJAX POST 数据到 ASP.NET Core 中的 MVC 控制器始终为空
【发布时间】:2020-10-08 18:36:10
【问题描述】:

我有一个 javascript 函数,它正在创建一个包含对象数组的模型,并使用 AJAX POST 请求将该数据发送到我的 MVC 控制器。出于某种原因,似乎可以传递给控制器​​的数组的大小是有限制的,在我的例子中,虽然是实验,但似乎在 450 到 500 个对象之间。一旦它大于该阈值,控制器将只收到一个空值。是否可以进行一些配置或解决方法来消除或解决此限制?

我已经尝试了几个基于 web.config 的“解决方案”,很多人就类似的 SO 问题提出了这些问题但无济于事(我认为这些可能仅适用于 .Net Framework 的 ASP.NET 版本,而不适用于 . NET 核心)。

Javascript:

var i = 0;
$("#SupplierNumber option").each(function () {
    var supplierNumber = {};
    supplierNumber.Value = $(this).val();
    supplierNumber.text = $(this).val();
    supplierNumbers.push(supplierNumber);
    //Below limits max size for testing
    i = i + 1;
    if (i > 450) {
        return false;
    }
});

//Other non-array values gathered here
var model = {
    "SupplierNumbers": supplierNumbers,
    //... other non-array values added to model
}

$.ajax({
    type: "POST",
    url: "/Administration/TestPost",
    data: model,
    dataType: "json",
    success: function (data) {
        alert("Finished");
    }
});

控制器:

[HttpPost]
public async Task<IActionResult> TestPost(TestViewModel model)
{
    //model is null here when array is > 500 in size 
    return Json(new { success = true });
}

【问题讨论】:

  • 我的回答有用吗?

标签: javascript jquery ajax asp.net-core asp.net-core-mvc


【解决方案1】:

在使用 JSON.stringify 之前试试这个!

我遇到了完全相同的问题。我需要做的就是:

在我的 Startup.cs 中,我在 ConfigureServices 中添加了以下几行:

services.Configure<FormOptions>(options =>
        {
            options.ValueCountLimit = int.MaxValue;
            options.ValueLengthLimit = int.MaxValue;
        });

【讨论】:

    【解决方案2】:

    这里有两个解决方案:

    第一个demo,使用json类型的数据,我们在ajax中一般使用这种方式传递数组(传递json类型的数据,需要在ajax中使用contentType: 'application/json',在action中使用[FromBody]):

    索引视图模型:

    public class IndexViewModel
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    

    控制器:

            [HttpGet]
            public IActionResult TestAjax() {
                return View();
            }
            [HttpPost]
            public IActionResult TestAjaxWithJsonData([FromBody]List<IndexViewModel> l) {
                return Ok();
            }
    

    查看:

     <button onclick="postdata1()">submit(jsondata)</button>
        
        
    @section scripts{ 
        <script type="text/javascript">
            function postdata1() {
                var a = [];
                for (var i = 0; i < 500; i++) {
                    var indexViewModel = {};
                    indexViewModel.Id = i;
                    indexViewModel.Name = "name" + i;
                    a.push(indexViewModel);
                }
                var data = JSON.stringify(a);
                $.ajax({
                    type: "POST",
                    url: 'TestAjaxWithJsonData',
                    data: data,
                    contentType: 'application/json'
                }).done(function (data) {
                });
            }
        </script>
    }
    

    结果:

    第二个demo,使用FormData:

    控制器:

    [HttpPost]
        public IActionResult TestAjaxWithFormdata(List<IndexViewModel> l)
        {
            return Ok();
        }
    

    查看:

    <button onclick="postdata2()">submit(formdata)</button>
        
        
    @section scripts{ 
        <script type="text/javascript">
            
            function postdata2() {
                var formdata = new FormData();
                for (var i = 0; i < 500; i++) {
                    formdata.append("l[" + i + "].Id", i);
                    formdata.append("l[" + i + "].Name", "name" + i);
                }
            $.ajax({
                    type: "POST",
                    url: 'TestAjaxWithFormdata',
                    cache: false,
                    contentType: false,
                    processData: false,
                    data: formdata,
                 }).done(function (data) {
            });
            }
            
        </script>
    }
    

    结果:

    【讨论】:

      【解决方案3】:

      我不知道确切的问题是什么,但你可以试试这个解决方案。在将字符串反序列化为对象之后,尝试将数据作为刺痛传递。

      var model = {
      "SupplierNumbers": supplierNumbers,
      //... other non-array values added to model
      }
      
      $.ajax({
      type: "POST",
      url: "/Administration/TestPost",
      data: {"data":JSON.stringify(model)},
      dataType: "json",
      success: function (data) {
          alert("Finished");
      }
      });
      

      在控制器端,您可以将此字符串反序列化为模型。

      [HttpPost]
      public async Task<IActionResult> TestPost(string data)
      {
       TestViewModel model=DeserializeObject<TestViewModel>(data);
      return Json(new { success = true });
      }
      

      【讨论】:

      • 这仍然会导致控制器接收到空值,但是如果我在构成模型的列表项上使用 JSON.stringify,它就可以工作。
      【解决方案4】:

      我们需要设置值的计数限制和长度。

      请在 startup.cs 中添加以下代码 --- 它对我有用

              services.AddMvc(options =>
              {
                  options.MaxModelBindingCollectionSize = 100000;
              });
      
              services.Configure<FormOptions>(options =>
              {
                  options.ValueCountLimit = int.MaxValue;
                  options.ValueLengthLimit = int.MaxValue;
                  options.MultipartHeadersLengthLimit = int.MaxValue;
              });
      

      【讨论】:

        【解决方案5】:

        经过一番搜索,我发现这是 ASP.NET Core 中的配置问题。默认情况下,可以绑定的复杂模型中的最大值数为 1024。在 Startup 类的 ConfigureServices 方法中添加以下选项将允许您将此限制增加到您需要的任何值 (MSDN)。

        services.AddMvc(options =>
        {
           options.MaxModelBindingCollectionSize = 100000;
        })
        

        另外,我发现人们在面对这个问题时可能会发现有用的其他东西,但是通过表单提交操作,下面的选项与上面提到的方法相同 (source)。

        services.Configure<FormOptions>(options => options.ValueCountLimit = 100000);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-11-22
          • 2021-09-15
          • 2020-12-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-09
          • 1970-01-01
          相关资源
          最近更新 更多