通过JSON发布一个对象数组到ASP.Net MVC3

我正在寻找一种解决scheme,通过JSON将对象数组发布到MVC3。

我正在使用的示例代码: http : //weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

JS:

var data = { ItemList: [ {Str: 'hi', Enabled: true} ], X: 1, Y: 2 }; $.ajax({ url: '/list/save', data: JSON.stringify(data), success: success, error: error, type: 'POST', contentType: 'application/json, charset=utf-8', dataType: 'json' }); 

ListViewModel.cs:

 public class ListViewModel { public List<ItemViewModel> ItemList { get; set; } public float X { get; set; } public float Y { get; set; } } 

ItemViewModel.cs:

 public class ItemViewModel { public string Str; // originally posted with: { get; set; } public bool Enabled; // originally posted with: { get; set; } } 

ListController.cs:

 public ActionResult Save(ListViewModel list) { // Do something } 

这篇文章的结果:

列表设置为ListViewModel
它的X和Y属性被设置
基础的ItemList属性被设置
ItemList包含一个项目,应该如此
该ItemList中的项目是未初始化的。 Str为空,Enabled为false。

换句话说,这是我从MVC3的模型绑定中得到的:

 list.X == 1 list.Y == 2 list.ItemList != null list.ItemList.Count == 1 list.ItemList[0] != null list.ItemList[0].Str == null 

它会出现MVC3 JsonValueProvider不适用于复杂的对象。 我如何得到这个工作? 我是否需要修改现有的MVC3 JsonValueProvider并修复它? 如果是的话,我怎样才能在MVC3项目中取代它呢?

相关的StackOverflow问题我已经追求无济于事:

Asp.net MVC Ajax JSON(后数组)使用MVC2和旧的基于表单的编码 – 该方法失败,包含一个对象数组的对象(JQuery无法正确编码)。

用JSON,JQuery发布一个复杂的对象数组到ASP.NET MVC控制器使用黑客我想避免在哪里接收一个普通的string,然后手动反序列化自己,而不是利用框架。

MVC3 RC2 JSONpost绑定无法正常工作没有他的内容types设置 – 它在我的代码中设置。

如何发布与JSON,jQuery的ASP.NET MVC控制器的复杂对象的数组? 这个可怜的人不得不写一个JsonFilter来parsing一个数组。 另一个黑客,我宁愿避免。

那么,我该如何做到这一点呢?

除了{ get; set; } { get; set; } { get; set; } ,这些是JSON绑定支持的一些条件:

  1. 这是ASP.NET MVC 3中的新function(请参阅“ JavaScript和AJAX改进 ”)。
  2. JSON对象的string(“X”,“Y”,“Str”和“Enabled”)必须与ViewModel对象的属性匹配。
  3. ViewModel对象的属性必须有{ get; set; } { get; set; } { get; set; }方法。
  4. 必须在请求中指定内容types为“application / json”。
  5. 如果它仍然不起作用,请检查JSONstring以确保它是有效的。

阅读更多在我的文章 。

希望有所帮助!

问题是List中模型中的属性没有获取/设置其公共属性。 换句话说,MVC3的自动JSON绑定仅适用于已获取和设置的对象属性。

这不会绑定:

 public string Str; 

这将绑定:

 public string Str { get; set; } 

真奇怪。 我无法重现你的行为。 这里是我的设置(ASP.NET MVC 3 RTM):

模型:

 public class ItemViewModel { public string Str { get; set; } public bool Enabled { get; set; } } public class ListViewModel { public List<ItemViewModel> ItemList { get; set; } public float X { get; set; } public float Y { get; set; } } 

控制器:

 public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpPost] public ActionResult Save(ListViewModel list) { return Json(list); } } 

视图:

 @{ ViewBag.Title = "Home Page"; } <script type="text/javascript"> $(function () { var data = { ItemList: [{ Str: 'hi', Enabled: true}], X: 1, Y: 2 }; $.ajax({ url: '@Url.Action("save", "home")', data: JSON.stringify(data), type: 'POST', contentType: 'application/json', dataType: 'json', success: function (result) { alert(result.ItemList[0].Str); } }); }); </script> 

运行这个警报"hi"并在Save行动中,一切正确初始化。

而只是为了logging什么是不工作的字典。 我已经打开了关于这个问题的票 。

我有一个类似的问题,发现对于一个复杂的对象,数字值被错过了。 他们进来了零。 即

  var person = { Name: "john", Age: 9 } 

被MVC控制器作为Person对象接收,其中属性被填充为Name=JohnAge=0

然后,我在Javascript中的年龄值是string…即

  var person = { Name: "john", Age: "9" } 

而这一切都挺好的…

这是因为MVC活页夹的吸引力。 但是,如果所有的JSON值都以string的forms出现,那么它们工作得非常好。

在JS中,如果你这样做

 var myObject = {thisNumber:1.6}; myObject.thisNumber=myObject.thisNumber-.6; 

它将评估为1而不是1.0

所以当你把它发送到服务器时,它会尝试绑定到一个名称的浮动,它不会find它,因为它是1而不是1.0。 微软的工程师们并没有想出一个默认的解决scheme。 我发现如果你绑定所有的绑定是足够聪明的find的东西。

所以在发送数据之前,通过运行它的string,也将所有的值转换为string。

以前所有的答案都是很好的指向我解决类似的问题。 我必须POST x-www-form-urlencoding而不是application/json (默认选项,如果contentType参数缺失)能够传递__RequestVerificationToken ,同时遇到问题时,数组中的对象属性不能绑定它们的值。 解决这个问题的方法是理解MVC模型绑定器的内部工作。

所以,基本上当您需要提供validation标记时,您将受到validation属性的限制。 而且您必须提供令牌作为参数,而不是您要发送的JSON对象的一部分。 如果你不使用ValidateAntiForgeryToken ,你可以相处JSON.stringify。 但是,如果你愿意,你不能通过令牌。

ContentTypex-www-form-urlencoding时,我嗅探到后端的stream量,我说我的复杂对象数组被序列化为类似的东西: klo[0][Count]=233&klo[0][Blobs]=94 。 这个数组最初是根对象的一部分,让我们说一些模型。 看起来像这样: model.klo = [{ Count: 233, Blobs: 94}, ...]

在后端,这个klo属性是由MVC活页夹创build的,具有与我发送的相同的元素数量。 但是这些元素本身并没有获得其属性的价值。

为了解决这个问题,我在客户端从模型对象中排除了klo属性。 在ajax函数中我写了这个代码:

 data: $.param(model) + "&" + arrayOfObjectsToFormEncoding("klo", [{ Count: 233, Blobs: 94}, ...]) .... function arrayOfObjectsToFormEncoding (modelPropertyName, arrayOfObjects) { var result = ""; if (arrayOfObjects && typeof arrayOfObjects == "object") { for (var i = 0; i < arrayOfObjects.length; i++) { var obj = arrayOfObjects[i]; if (obj) { for (var p in obj) { if (obj.hasOwnProperty(p)) { result += encodeURIComponent(modelPropertyName + "[" + i + "]." + p) + "=" + encodeURIComponent(obj[p]) + "&"; } } } } } if (result[result.length - 1] == "&") { result = result.substr(0, result.length - 1); } return result; } 

该函数将复杂对象的数组转换为MVC-binder所识别的forms。 forms是klo[0].Count=233&klo[0].Blobs=94