【问题标题】:MVC3 Complex JSON List BindingMVC3 复杂 JSON 列表绑定
【发布时间】:2012-03-19 14:09:12
【问题描述】:

让 ASP.NET MVC3 绑定包含列表的复杂 JSON 对象时遇到问题。

这是我的对象的结构。

public class PageModel
{
    public PageModel() { }
    public CustomObject1 CustomObject { get; set; }
    public IEnumerable<CustomObject2> Objects { get; set; }

}

public class CustomObject1
{
    public CustomObject1() { }
    [Required]
    public int CustomId1 { get; set; }
    public string CustomName { get; set; }
}

public class CustomObject2
{
    public CustomObject2() { }
    [Required]
    public int Custom2Id { get; set; }
    public CustomObject3 SubItem { get; set; }
    public int SubItemId { get; set; }
}

您可以假设CustomObject3 具有相似的结构 - 无需复制另一个组成的类,所以我认为您可以发挥您的想象力 :)

这是进行 POST 调用的 Javascript/Jquery(假设所有导致此调用的 JS 都提供了正确的数据):

//$obj1 has all data for the first object
var firstObj = { };
firstObj.CustomId1 = $obj1.Id;
firstObj.CustomName = $obj1.Name;

var i = 0;

//$objects is an array with all the data
$.each($objects, function() {
    objsArray[i] = {
    Custom2Id: $(this).Id,
    SubItemId: $(this).itemId
    };

    ++i;
});

$.ajax({
    type: 'POST',
    url: '/Action/Method',
    data: { CustomObject: firstObj, Objects: objsArray },
    //Success/error handlers here
});

最后(我知道,相当多的代码)这里是我所拥有的方法的概述:

public class ActionController : Controller {
    public JsonResult Method(PageModel model) {
        //Gets here - model.CustomObject is filled correctly, and model.Objects has a correct count of whatever data I passed to the method - but all of the properties are empty!
    }
}

正如我所说,当我调试和单步执行时,第一个对象已填充,所有数据都在那里。如果我在 JSON 对象的 Objects 数组中传递两个对象,我会在控制器中看到 Count 为 2,但 Custom2IdSubItemId 是空的。什么给了?

当我在$.ajax 调用中指定'application/json'contentType 时,MVC 抱怨正在传递的数据。也试过将MVC方法中的model参数拆分成两个单独的参数,但是没有用。

任何帮助都非常感谢 - 这个让我很难过!

【问题讨论】:

    标签: jquery json asp.net-mvc-3


    【解决方案1】:

    因此,这个特定问题的解决方案是在 SO 其他地方找到的两个或多个解决方案的组合(其中一个可能是 Jakub 的答案围绕使用通用集合类型 - IEnumerable - 而不是更多具体的一个 - List)。

    首先,不需要更改服务器端代码 - 这方面一切正常。需要进行的所有更改都在客户端,特别是 jQuery 和您的 Javascript 如何将数据发送到所述服务器。

    这是旧的 Javascript:

    $.ajax({
        type: 'POST',
        url: '/Action/Method',
        data: { CustomObject: firstObj, Objects: objsArray },
        //Success/error handlers here
    });
    

    这里的第一个问题是 Javascript 没有通知服务器 '/Action/Method' 你到底发送了什么(它是二进制的,是参数的混合,还是 JSON?)所以添加一个 contentType: 'application/json' 行将达到这个目的。当你这样做时,服务器就会知道它必须解码 JSON...

    但就目前而言,解码将失败,并在代码甚至进入您的方法之前抛出异常(“Invalid JSON primitive”)(然后由 MVC 处理解码和绑定)。在上面的 AJAX 调用中,我在 $.ajax 选项中构建了一个新的 JSON 对象,但是发送的 JSON 不会通过 JSON 验证器(James Kyburz 提到了一个很棒的 JSON 验证器:JSONLint Validator)。相反,在 $.ajax 调用之前创建 JSON 对象,并将对象字符串化,使其具有正确的 JSON 格式。总而言之,AJAX 调用应该如下所示:

    var dataObj = { CustomObject: firstObj, Objects: objsArray };
    
    $.ajax({
        type: 'POST',
        url: '/Action/Method',
        contentType: 'application/json',
        data: JSON.stringify(dataObj),
        //Success/error handlers here
    });
    

    【讨论】:

    • 经过数小时寻找功能齐全的代码,这解决了我的问题!谢谢!!
    【解决方案2】:

    public IEnumerable&lt;CustomObject2&gt; Objects { get; set; } 更改为List&lt;CustomObject2&gt;

    模型绑定器不知道如何创建IEnumerable 接口的实例,它需要更具体的东西。

    你还需要改变这个:

    data: { CustomObject: firstObj, Objects: objsArray }

    进入

    data: { model: { CustomObject: firstObj, Objects: objsArray } }

    model 部分与您的操作中的参数名称匹配。

    【讨论】:

    • 我玩过这个 - IEnumerableIListList 都产生相同的结果 - 一个包含正确数量的没有值的对象的列表。
    • 我不同意你的第二部分 - 虽然它在某些情况下可能会有所帮助,但 MVC3 足够聪明,可以识别我传递给它的数据属于我的 model 参数。我上面描述的工作解决方案没有指定额外的对象层来安抚 MVC - 它能够辨别我在做什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多