通过 JSON 将对象数组发布到 ASP.Net MVC3
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4789481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Post an Array of Objects via JSON to ASP.Net MVC3
提问by Chris Moschini
I'm looking for a solution to POSTing an array of objects to MVC3 via JSON.
我正在寻找通过 JSON 将对象数组发布到 MVC3 的解决方案。
Example code I'm working off of: http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx
我正在使用的示例代码:http: //weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx
JS:
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:
ListViewModel.cs:
public class ListViewModel
{
public List<ItemViewModel> ItemList { get; set; }
public float X { get; set; }
public float Y { get; set; }
}
ItemViewModel.cs:
ItemViewModel.cs:
public class ItemViewModel
{
public string Str; // originally posted with: { get; set; }
public bool Enabled; // originally posted with: { get; set; }
}
ListController.cs:
列表控制器.cs:
public ActionResult Save(ListViewModel list)
{
// Do something
}
The result of this POST:
这个帖子的结果:
list is set, to a ListViewModel
Its X and Y properties are set
The underlying ItemList property is set
The ItemList contains one item, as it should
The item in that ItemList is uninitialized. Str is null and Enabled is false.
list 被设置为 ListViewModel
其 X 和 Y 属性被设置
底层 ItemList 属性被设置
ItemList 包含一个项目,因为它应该
ItemList 中的项目未初始化。Str 为空,启用为假。
Put another way, this is what I get from MVC3's model binding:
换句话说,这就是我从 MVC3 的模型绑定中得到的:
list.X == 1
list.Y == 2
list.ItemList != null
list.ItemList.Count == 1
list.ItemList[0] != null
list.ItemList[0].Str == null
It would appear the MVC3 JsonValueProvider is not working for complex objects. How do I get this to work? Do I need to modify the existing MVC3 JsonValueProvider and fix it? If so, how do I get at it and replace it in an MVC3 project?
MVC3 JsonValueProvider 似乎不适用于复杂对象。我如何让这个工作?我是否需要修改现有的 MVC3 JsonValueProvider 并修复它?如果是这样,我如何获得它并在 MVC3 项目中替换它?
Related StackOverflow questions I've already pursued to no avail:
我已经尝试过的相关 StackOverflow 问题无济于事:
Asp.net Mvc Ajax Json (post Array)Uses MVC2 and older form-based encoding - that approach fails with an object that contains an array of objects (JQuery fails to encode it properly).
Asp.net Mvc Ajax Json (post Array)使用 MVC2 和更旧的基于表单的编码 - 该方法因包含对象数组的对象而失败(JQuery 无法对其进行正确编码)。
Post an array of complex objects with JSON, JQuery to ASP.NET MVC ControllerUses a hack I'd like to avoid where the Controller instead receives a plain string which it then manually deserializes itself, rather than leveraging the framework.
使用 JSON、JQuery 将一组复杂对象发布到 ASP.NET MVC 控制器使用一个 hack 我想避免控制器接收一个普通字符串,然后手动反序列化自己,而不是利用框架。
MVC3 RC2 JSON Post Binding not working correctly Didn't have his content-type set - it's set in my code.
MVC3 RC2 JSON Post Binding 无法正常工作没有设置他的内容类型 - 它在我的代码中设置。
How to post an array of complex objects with JSON, jQuery to ASP.NET MVC Controller?This poor guy had to write a JsonFilter just to parse an array. Another hack I'd prefer to avoid.
如何使用 JSON、jQuery 将一组复杂对象发布到 ASP.NET MVC 控制器?这个可怜的家伙不得不编写一个 JsonFilter 来解析一个数组。另一个我宁愿避免的黑客。
So, how do I make this happen?
那么,我该如何实现呢?
采纳答案by Chris Moschini
The problem was that the properties in the models that were in the List did not have get/set on their public properties. Put another way, MVC3's automatic JSON binding only works on object properties that have get and set.
问题是 List 中模型中的属性在其公共属性上没有 get/set 。换句话说,MVC3 的自动 JSON 绑定仅适用于具有 get 和 set 的对象属性。
This will not bind:
这不会绑定:
public string Str;
This will bind:
这将绑定:
public string Str { get; set; }
回答by stack247
In addition to { get; set; }, these are some of the conditions for JSON Binding Support:
除了{ get; set; },这些是 JSON 绑定支持的一些条件:
- This is new feature in ASP.NET MVC 3 (See “JavaScript and AJAX Improvements“).
- The JSON object's strings (‘X', ‘Y', ‘Str', and ‘Enabled') must match ViewModel object's properties.
- ViewModel object's properties must have
{ get; set; }method. - Must specify Content Type as “application/json” in the request.
- If it's still not working, check the JSON string to make sure it's valid one.
- 这是 ASP.NET MVC 3 中的新功能(请参阅“ JavaScript 和 AJAX 改进”)。
- JSON 对象的字符串('X'、'Y'、'Str' 和 'Enabled')必须与 ViewModel 对象的属性匹配。
- ViewModel 对象的属性必须有
{ get; set; }方法。 - 必须在请求中将内容类型指定为“application/json”。
- 如果它仍然不起作用,请检查 JSON 字符串以确保它是有效的。
Read more at my post.
在我的帖子中阅读更多内容。
Hope that helps!
希望有帮助!
回答by Darin Dimitrov
That's strange. I am unable to reproduce your behavior. Here's my setup (ASP.NET MVC 3 RTM):
真奇怪。我无法重现您的行为。这是我的设置(ASP.NET MVC 3 RTM):
Model:
模型:
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; }
}
Controller:
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Save(ListViewModel list)
{
return Json(list);
}
}
View:
看法:
@{
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>
Running this alerts "hi"and inside the Saveaction everything is correctly initialized.
运行此警报"hi"并在Save操作中正确初始化所有内容。
And just for the record what doesn't work are Dictionaries. I've opened a ticketabout the issue.
回答by Dev
I had a similar issue, and found that for a complex object, the numeric values were getting missed. They were coming in as zeros. i.e.
我有一个类似的问题,发现对于一个复杂的对象,数值被遗漏了。它们以零的形式出现。IE
var person = {
Name: "john",
Age: 9
}
was being received by MVC controller as a Person object where the properties were being populated as Name=Johnand Age=0.
被 MVC 控制器作为 Person 对象接收,其中的属性被填充为Name=John和Age=0。
I then made the Age value in Javascript to be string... i.e.
然后我将 Javascript 中的 Age 值设为字符串...即
var person = {
Name: "john",
Age: "9"
}
And this came through just fine...
这一切都很好……
回答by Chris Stephens
Its because the MVC binders kind of suck. However, they do work pretty well if all JSON values come over as a string.
这是因为 MVC 活页夹有点糟糕。但是,如果所有 JSON 值都作为字符串出现,它们确实可以很好地工作。
In JS if you do this
在 JS 中,如果你这样做
var myObject = {thisNumber:1.6};
myObject.thisNumber=myObject.thisNumber-.6;
It will evaluate to 1 not to 1.0
它将评估为 1 而不是 1.0
So when you sent it over to the server it will try to bind to a float of that name and it will not find it since it came over as 1 instead of 1.0. Its very lame and crazy that MS engineers did not come up with a default solution to this. I find if you string everything the bindings are smart enough to find things.
因此,当您将它发送到服务器时,它会尝试绑定到该名称的浮点数,但由于它是 1 而不是 1.0,因此它不会找到它。MS 工程师没有想出一个默认的解决方案,这是非常蹩脚和疯狂的。我发现如果你把所有东西都串起来,绑定就足够聪明来找到东西了。
So before sending the data over run it though a stringifier that will also convert all values to strings.
因此,在发送数据之前,通过字符串化器运行它,该字符串化器也将所有值转换为字符串。
回答by Victor Ponamarev
All previous answers were great to point me to solution of the similar problem. I had to POST x-www-form-urlencodinginstead of application/json(default option if contentType parameter is missing) to be able to pass __RequestVerificationTokenand simultaneously faced with problem when object properties being in the array do not bind their values. The way to solve the issue is to understand internal work of MVC model binder.
以前的所有答案都很好地为我指出了类似问题的解决方案。当数组中的对象属性没有绑定它们的值时,我不得不 POSTx-www-form-urlencoding而不是application/json(如果缺少 contentType 参数的默认选项)能够传递__RequestVerificationToken并同时面临问题。解决问题的方法是了解MVC模型绑定器的内部工作。
So, basically when you need to supply verification token you are restricted with validation attribute. And you must provide the token as the parameter not as a part of the JSON-object you are sending. If you would not use ValidateAntiForgeryToken, you could get along with JSON.stringify. But if you would, you could not pass the token.
因此,基本上当您需要提供验证令牌时,您会受到验证属性的限制。并且您必须提供令牌作为参数,而不是作为您发送的 JSON 对象的一部分。如果您不使用ValidateAntiForgeryToken,则可以使用 JSON.stringify。但是,如果您愿意,您将无法传递令牌。
I sniffed traffic to backend when ContentTypewas x-www-form-urlencodingand I remarked that my array of complex objects was serialized to something like that: klo[0][Count]=233&klo[0][Blobs]=94. This array initially was a part of root object, let's say some model. It looked like that: model.klo = [{ Count: 233, Blobs: 94}, ...].
我闻流量后端时,ContentType是x-www-form-urlencoding和我说过,我的复杂对象的数组被序列化到类似的东西:klo[0][Count]=233&klo[0][Blobs]=94。这个数组最初是根对象的一部分,让我们说一些模型。它看起来像这样:model.klo = [{ Count: 233, Blobs: 94}, ...]。
At the backend side this kloproperty was creating by MVC binder with the same elements count that I sent. But these elements itself did not obtain values for their properties.
在后端,此klo属性由 MVC 绑定器创建,元素计数与我发送的相同。但是这些元素本身并没有为其属性获得值。
SOLUTION
解决方案
To deal with this I excluded kloproperty from the model object at the client side. In the ajaxfunction I wrote this code:
为了解决这个问题,我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;
}
The function transforms array of complex object into form that is recognized by MVC-binder. The form is klo[0].Count=233&klo[0].Blobs=94.
该函数将复杂对象数组转换为 MVC-binder 可识别的形式。形式是klo[0].Count=233&klo[0].Blobs=94。

