MVC3复杂JSON列表绑定

Mat*_*abe 8 jquery json asp.net-mvc-3

让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; }
}
Run Code Online (Sandbox Code Playgroud)

你可以假设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
});
Run Code Online (Sandbox Code Playgroud)

最后(我知道,相当一些代码)这里是我的方法的概述:

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!
    }
}
Run Code Online (Sandbox Code Playgroud)

正如我所说,第一个对象被填充,当我调试并逐步执行时,所有数据都在那里.如果我中通过两个对象Objects在JSON对象阵列,我看到Count的2在控制器,但Custom2IdSubItemId是空的.是什么赋予了?

当我在调用中指定一个contentType时,MVC会抱怨传递的数据.还尝试将MVC方法中的参数拆分为两个单独的参数,但它没有帮助.'application/json'$.ajaxmodel

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

Mat*_*abe 5

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

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

这是旧的Javascript:

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

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

但正如它现在所说的那样,解码将失败,Invalid JSON primitive在代码甚至进入你的方法之前抛出异常(" ")(MVC然后处理解码和绑定).在上面的AJAX调用中,我在$.ajax选项中构建了一个新的JSON对象,但是发送的JSON不会传递JSON验证器(James Kyburz提到了一个很棒的JSON验证器:JSONLint验证器).相反,在$.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
});
Run Code Online (Sandbox Code Playgroud)