通过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绑定支持的一些条件:
- 这是ASP.NET MVC 3中的新function(请参阅“ JavaScript和AJAX改进 ”)。
- JSON对象的string(“X”,“Y”,“Str”和“Enabled”)必须与ViewModel对象的属性匹配。
- ViewModel对象的属性必须有
{ get; set; }
{ get; set; }
{ get; set; }
方法。 - 必须在请求中指定内容types为“application / json”。
- 如果它仍然不起作用,请检查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=John
和Age=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。 但是,如果你愿意,你不能通过令牌。
当ContentType
是x-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
。