You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Asp.Net Core模型绑定问题:Ajax提交列表数据无法映射

解决ASP.NET Core中JQuery Ajax提交列表数据无法绑定到模型的问题

问题背景

在ASP.NET Core Web应用中,使用JQuery Ajax提交表单变更时,由于可编辑表格没有常规输入字段,需要手动向请求中追加ListProductSubCategories数据,但服务器端模型始终无法获取该列表值,收到的是空列表。

模型定义

public class ProductCategoryModel {
    public ProductCategoryDto Category { get; set; } = new();
}

public class ProductCategoryDto
{
    public string Description { get; set; } = default!;
    public List<ProductSubCategoryDto> ListProductSubCategories { get; set; } = new();
}

public class ProductSubCategoryDto
{
    public Guid? Id { get; set; }
    public string Description { get; set; } = default!;
}

原有效请求格式

仅提交单个字段时,模型绑定正常工作:

[{"name":"Model.Category.Description","value":"CATEGORY"}]

失败的尝试方式

方式一:直接追加数组对象

[{"name":"Model.Category.Description","value":"CATEGORY"},
{"name":"Model.Category.ListProductSubCategories",
 "value":[
    {"Id":null,"Description":"Nouvelle sous-catégorie"},
    {"Id":null,"Description":"Nouvelle sous-catégorie 2"}
 ]
}]

方式二:重复追加同一键名

[{"name":"Model.Category.Description","value":"CATEGORY"},
{"name":"Model.Category.ListProductSubCategories","value":{"Id":null,"Description":"Nouvelle sous-catégorie"}},
{"name":"Model.Category.ListProductSubCategories","value":{"Id":null,"Description":"Nouvelle sous-catégorie 2"}}]

原因分析

ASP.NET Core的模型绑定对application/x-www-form-urlencoded格式(即serializeArray生成的表单编码格式)有特定要求:列表数据必须通过索引下标标识每个元素的属性,不能直接传递数组对象或重复使用同一键名。这种格式下,列表元素的键名需要形如Model.Category.ListProductSubCategories[0].Description。

解决方案

方案一:生成带索引的表单键值对

修改客户端代码,遍历子分类列表,生成带索引的键值对并逐个添加到请求数据中:

function mapAssociatedToSimpleArray(obj) {
    var a3 = Object.keys(obj).map(function (k) { return obj[k]; })
    return a3;
}

var data = $("#form").serializeArray();

var listSubCategories = mapAssociatedToSimpleArray(_dataSource); 

// 遍历子分类,生成带索引的键值对
listSubCategories.forEach(function(subCat, index) {
    data.push({ name: `Model.Category.ListProductSubCategories[${index}].Id`, value: subCat.Id });
    data.push({ name: `Model.Category.ListProductSubCategories[${index}].Description`, value: subCat.Description });
});
        
$.ajax({
    url: "/inv/ProductsCategoriesController/Edit/@Model.Categorie.Id",
    type: 'POST',
    dataType: 'json',
    data: data,
    headers: {'RequestVerificationToken': $(".AntiForge input").val() },
    success: function (data) {        
        // 处理成功逻辑
    },
    error: function (xhr, ajaxOptions, thrownError) {
        if (utils.hasJsonStructure(xhr.responseText)) {
            $("#form").handleModelErrors(JSON.parse(xhr.responseText));
        }
        notifications.error();
    }            
});   

生成的请求数据示例:

[{"name":"Model.Category.Description","value":"CATEGORY"},
{"name":"Model.Category.ListProductSubCategories[0].Id","value":null},
{"name":"Model.Category.ListProductSubCategories[0].Description","value":"Nouvelle sous-catégorie"},
{"name":"Model.Category.ListProductSubCategories[1].Id","value":null},
{"name":"Model.Category.ListProductSubCategories[1].Description","value":"Nouvelle sous-catégorie 2"}]

方案二:直接提交JSON格式数据

如果不想处理表单编码的索引格式,可以将整个数据序列化为JSON字符串,设置请求头为application/json,让模型绑定直接解析JSON:

// 将表单数据转为对象
var formData = $("#form").serializeArray();
var model = {};
formData.forEach(function(item) {
    // 解析嵌套属性路径
    var keys = item.name.split('.');
    var current = model;
    for(var i = 0; i < keys.length; i++) {
        if(i === keys.length - 1) {
            current[keys[i]] = item.value;
        } else {
            current[keys[i]] = current[keys[i]] || {};
            current = current[keys[i]];
        }
    }
});

// 添加子分类列表
model.Category.ListProductSubCategories = mapAssociatedToSimpleArray(_dataSource);

$.ajax({
    url: "/inv/ProductsCategoriesController/Edit/@Model.Categorie.Id",
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json', // 关键:指定JSON内容类型
    data: JSON.stringify(model), // 序列化为JSON字符串
    headers: {'RequestVerificationToken': $(".AntiForge input").val() },
    success: function (data) {        
        // 处理成功逻辑
    },
    error: function (xhr, ajaxOptions, thrownError) {
        if (utils.hasJsonStructure(xhr.responseText)) {
            $("#form").handleModelErrors(JSON.parse(xhr.responseText));
        }
        notifications.error();
    }            
});   

内容的提问来源于stack exchange,提问作者M.Parent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:43:19