【问题标题】:Model binding is not able to bind string array when post as JSON object当作为 JSON 对象发布时,模型绑定无法绑定字符串数组
【发布时间】:2020-09-01 17:47:40
【问题描述】:

我有以下 jQuery 扩展来将表单序列化为 Json 对象

(function () {
    $.fn.serializeObject = function () {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function () {
            if (o[this.name]) {
                if ((typeof (this.value) === "boolean") ||
                    (typeof (this.value) === "string" && this.value != undefined && (this.value.toLowerCase() === "true" || this.value.toLowerCase() === "false"))) {
                    o[this.name] = ((o[this.name] == "true") | (this.value == "true")) ? true : false; //Sets value to true if one of two bits is true
                }
                else {
                    if (!o[this.name].push) {
                        o[this.name] = [o[this.name]];
                    }
                    o[this.name].push(this.value || '');
                }
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };
})(jQuery)

然后我有 Html 表单

<form id="myform">
    <input name"AccountNumbers[0]" value="1111" />
    <input name"AccountNumbers[1]" value="2222" />
    // some other properties
</form>

然后使用 Ajax 我将表单发布到服务器

var obj = $("#myform").serializeObject();
   $.ajax({
            type: "POST",
            data: JSON.stringify(obj),
            url: "/save",
            contentType: "application/json; charset=utf-8",
            processData: true,
            cache: false
        })

serializeObject 方法创建 json 对象为

{
   "AccountNumbers[0]: "1111",
   "AccountNumbers[1]: "2222"
  ....
  ....      
}

我正在使用 ASP.NET Core。所以在服务器上我有控制器操作方法

    public class MyModel
    {
        public string[] AccountNumbers {get;set;}

        // some other properties
    }

    [HttpPost]
    public async Task<IActionResult> Save([FromBody]MyModel model)
    {
        // do something
    }

问题:在服务器上,模型的所有属性都被填充,除了AccountNumbers。不知何故模型绑定无法绑定字符串数组。

更新 1
正如下面的 cmets 所指出的,是数组结构。我已经更改了我的 jQuery 扩展,但是它只适用于一个级别。但如果我有层次结构,那么它就行不通了

(function () {
    $.fn.serializeObject = function () {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function () {
            var name = this.name;
            var val = this.value;
            if (name && name.indexOf("[") > -1) {
                name = name.substr(0, name.lastIndexOf("["));
            }

            if (o[name]) {
                if ((typeof (val) === "boolean") ||
                    (typeof (val) === "string" && val != undefined && (val.toLowerCase() === "true" || val.toLowerCase() === "false"))) {
                    o[name] = ((o[name] == "true") | (val == "true")) ? true : false; //Sets value to true if one of two bits is true
                }
                else {
                    if (!o[name].push) {
                        o[name] = [o[name]];
                    }
                    o[name].push(val || '');
                }
            } else {
                o[name] = val || '';
            }
        });
        return o;
    };
})(jQuery)

该扩展不适用于

<input name="Person[0].AccountNumber[0]" value="1111" />
<input name="Person[0].AccountNumber[1]" value="2222" />
<input name="Person[1].AccountNumber[0]" value="3333" />
<input name="Person[1].AccountNumber[1]" value="4444" />

【问题讨论】:

  • 通过层次结构,您可以调整您的解决方案以递归解析各个部分。但是,在这个阶段,考虑为更复杂的结构使用数据绑定引擎可能是有意义的。像 Vue 这样的东西可以满足你的需求,因为它不需要太多就可以放入页面。
  • 使用 Vue 就像是彻底改变了架构。我需要这个才能在一页上工作

标签: jquery asp.net asp.net-core json.net model-binding


【解决方案1】:

您需要将 JSON 正文上的 AccountNumbers 属性更新为数组类型。 ASP.NET Core 将每个索引的 AccountNumbers 属性视为不同的属性,而不是集合的一部分。

这样的事情应该可以工作:

{
  AccountNumbers: ["1111", "2222"]
}

如果这是一个 GET 请求,您可以将数组的每个项目作为具有相同名称的查询字符串参数传递。 例如:

/save?AccountNumbers=1111&AccountNumbers=2222

注意:此方法不适用于 JSON POST 正文,因为有效 JSON 中不允许重复键。

【讨论】:

  • 你说得对,我需要更改我的 jQuery 扩展来创建正确的数组结构。
猜你喜欢
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多