2012-03-19 78 views
8

有问题让ASP.NET MVC3绑定我包含列表的复杂JSON对象。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是结构相似 - 不需要重复又由阶级,所以我想你可以用你的想象力:)

下面是使用Javascript/jQuery的,使POST调用(假设所有的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,但Custom2IdSubItemId为空。是什么赋予了?

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

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

回答

5

因此,这个特定问题的解决方案是在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 
}); 
+0

感谢这有助于很多:)! – Rookian 2012-11-28 17:02:23

+0

经过数小时寻求完整功能的代码,这解决了我的问题!谢谢!! – 2013-08-12 17:22:22

3

变化public IEnumerable<CustomObject2> Objects { get; set; }List<CustomObject2>

型粘合剂不知道如何创建IEnumerable接口的一个实例,它需要更具体的东西。

你也需要改变这一点:

data: { CustomObject: firstObj, Objects: objsArray }

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

model部分在动作参数的名称相匹配。

+0

我已经打得四处这一点 - 'IEnumerable','IList','List'都产生相同的结果 - 用正确数量的对象列表,没有价值。 – Mattygabe 2012-03-19 14:18:17

+0

我不同意你的第二部分 - 尽管它在某些情况下可能有所帮助,但MVC3足够聪明,可以辨别出我传递给它的数据属于我的“模型”参数。我上面描述的工作解决方案没有指定额外的对象层来安抚MVC - 它能够辨别我在做什么。 – Mattygabe 2012-03-21 19:03:54