让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,但Custom2Id
和SubItemId
为空。是什么给了什么?
当我在contentType
调用中指定'application/json'
$.ajax
时,MVC会抱怨传递的数据。还尝试将MVC方法中的model
参数拆分为两个单独的参数,但它没有帮助。
非常感谢任何帮助 - 这个让我难过!
答案 0 :(得分: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?)所以添加{{ 1}}行将用于此目的。执行此操作时,服务器会知道它必须解码JSON ...
但是就像它现在所说的那样,在代码甚至进入你的方法之前,解码将失败并抛出异常(“contentType: 'application/json'
”)(然后MVC处理解码和绑定)。在上面的AJAX调用中,我在Invalid JSON primitive
选项中构建了一个新的JSON对象,但是发送的JSON不会传递JSON验证器(James Kyburz提到了一个很棒的JSON验证器:JSONLint Validator)。相反,在$.ajax
调用之前创建JSON对象,并将对象字符串化,使其处于正确的JSON格式。总而言之,这是AJAX调用的样子:
$.ajax
答案 1 :(得分:3)
将public IEnumerable<CustomObject2> Objects { get; set; }
更改为List<CustomObject2>
模型绑定器不知道如何创建IEnumerable
接口的实例,它需要更具体的东西。
您还需要更改此内容:
data: { CustomObject: firstObj, Objects: objsArray }
到
data: { model: { CustomObject: firstObj, Objects: objsArray } }
model
部分与您的操作中的参数名称相匹配。