Send an array of objects via JSON for ASP.Net MVC3

I am looking for a solution for POSTing an array of MVC3 objects via JSON.

Sample code I'm working on: 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 } 

The result of this POST:

list is set in ListViewModel
Its X and Y properties are set. The entered ItemList property is set. The ItemList contains one item because it must. The item in this ItemList is not initialized. Str is null and Enabled is false.

In other words, this is what I get from MVC3 model binding:

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

It would seem that MVC3 JsonValueProvider does not work for complex objects. How do I make this work? Do I need to modify an existing MVC3 JsonValueProvider and fix it? If so, how do I get to it and replace it in the MVC3 project?

Related StackOverflow questions that I have already pursued to no avail:

Asp.net Mvc Ajax Json (post Array) Uses MVC2 and the old forms-based encoding - this approach fails with an object that contains an array of objects (JQuery cannot encode it correctly).

Publish an array of complex objects using JSON, JQuery for ASP.NET MVC Controller Uses a hack that I would like to avoid when the controller receives a regular string, which it manually deserializes by itself rather than using a framework.

MVC3 RC2 JSON Post Binding does not work correctly It did not have its own set of content - it is installed in my code.

How to host an array of complex objects using JSON, jQuery for ASP.NET MVC Controller? This poor guy had to write JsonFilter to parse the array. Another hack I would rather avoid.

So how do I do this?

+65
json arrays post asp.net-mvc-3
Jan 25 2018-11-11T00:
source share
6 answers

The problem was that the properties in the models that were in the List did not have / did not set their public properties. In other words, automatic JSON binding MVC3 only works with objects that have get and set.

This will not bind:

 public string Str; 

This will link:

 public string Str { get; set; } 
+30
Feb 02 2018-11-11T00:
source share
β€” -

In addition to { get; set; } { get; set; } { get; set; } , these are some of the JSON binding support conditions:

  • This is a new feature in ASP.NET MVC 3 (see " JavaScript and AJAX Enhancements ").
  • JSON object strings ('X,' Y, 'Str, and' Enabled) must match ViewModel object properties.
  • ViewModel object properties must have a { get; set; } { get; set; } { get; set; } .
  • In the request, specify the content type as "application / json".
  • If it still does not work, check the JSON string to make sure it is valid.

Read more on my post .

Hope this helps!

+43
Mar 21 2018-11-11T00:
source share

This is strange. I can not reproduce your behavior. Here is my setup (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> 

These warnings are "hi" and inside the Save action, everything is correctly initialized.

And just for the record, what doesn't work is dictionaries. I opened a ticket about the problem.

+28
Jan 25 '11 at 8:26
source share

I had a similar problem, and I found that for a complex object, numeric values ​​are skipped. They walked like zeros. i.e.

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

was accepted by the MVC as a Person object, where the properties were populated with Name=John and Age=0 .

Then I made the Age value in Javascript for the string ... i.e.

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

And it worked out just fine ...

+3
Sep 18 '11 at 12:02
source share

This is because MVC bundles seem to suck. However, they work very well if all JSON values ​​are passed as a string.

In JS, if you do it

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

It will evaluate to 1 not to 1.0

Therefore, when you sent it to the server, it will try to associate this name with the float, and it will not find it, since it appeared as 1 instead of 1.0. Its very lame and crazy that MS engineers did not come up with a default solution for this. I find that you bind all the bindings smart enough to find things.

So, before sending data, run it, although a string one, which also converts all values ​​to strings.

0
Jan 09 '12 at 17:55
source share

All of the previous answers were great to point to a solution to a similar problem. I had to POST x-www-form-urlencoding instead of application/json (the default option if the contentType parameter is missing) in order to be able to pass __RequestVerificationToken and at the same time run into a problem when the properties of the object in the array do not bind their values . The way to solve the problem is to understand the internal workings of the MVC middleware.

So basically, when you need to put a validation token, you are limited to the validation attribute. And you must provide the token as a parameter, not as part of the JSON being sent. If you would not use the ValidateAntiForgeryToken , you could agree to JSON.stringify. But if you do, you cannot transfer the token.

I sniffed the traffic on the backend when ContentType was x-www-form-urlencoding , and I noticed that my array of complex objects was serialized something like this: klo[0][Count]=233&klo[0][Blobs]=94 . This array was originally part of the root object, say, of some model. It looked like this: model.klo = [{ Count: 233, Blobs: 94}, ...] .

On the backend side, this klo property klo created by the MVC klo with the same element counts that I sent. But these elements themselves did not receive values ​​for their properties.

Decision

To handle this, I excluded the klo property from the client side model object. In ajax function, I wrote this code:

 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 converts an array of a complex object into a form that is recognized by the MVC binder. The form klo[0].Count=233&klo[0].Blobs=94 .

0
Jan 15 '15 at 18:23
source share



All Articles