Publier un tableau d’objects via JSON vers ASP.Net MVC3

Je cherche une solution pour POST d’un tableau d’objects vers MVC3 via JSON.

Exemple de code sur lequel je travaille: 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.ssortingngify(data), success: success, error: error, type: 'POST', contentType: 'application/json, charset=utf-8', dataType: 'json' }); 

ListViewModel.cs:

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

ItemViewModel.cs:

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

ListController.cs:

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

Le résultat de ce POST:

liste est définie, à un ListViewModel
Ses propriétés X et Y sont définies
La propriété ItemList sous-jacente est définie
La ItemList contient un élément, comme il se doit
L’élément de cette ItemList n’est pas initialisé. Str est nul et Activé est faux.

En d’autres termes, voici ce que j’obtiens de la liaison de modèle de MVC3:

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

Il semblerait que le MVC3 JsonValueProvider ne fonctionne pas pour les objects complexes. Comment puis-je que cela fonctionne? Dois-je modifier le JSJValueProvider existant de MVC3 et le corriger? Si oui, comment puis-je y accéder et le remplacer dans un projet MVC3?

Questions relatives à StackOverflow auxquelles j’ai déjà répondu en vain:

Asp.net Mvc Ajax Json (post Array) Utilise MVC2 et l’ancien encodage basé sur des formulaires – cette approche échoue avec un object qui contient un tableau d’objects (JQuery ne parvient pas à le coder correctement).

Publiez un tableau d’objects complexes avec JSON, JQuery vers ASP.NET MVC Controller Utilise un hack que je voudrais éviter, mais à la place, le Controller reçoit une chaîne simple qu’il désérialise ensuite manuellement, plutôt que de tirer parti de la structure.

MVC3 RC2 JSON Post Binding ne fonctionne pas correctement Son code de type de contenu n’est pas défini – il est défini dans mon code.

Comment publier un tableau d’objects complexes avec JSON, jQuery vers ASP.NET MVC Controller? Ce pauvre gars a dû écrire un JsonFilter juste pour parsingr un tableau. Un autre hack que je préfère éviter.

Alors, comment puis-je y arriver?

En plus de { get; set; } { get; set; } { get; set; } , voici certaines des conditions pour le support de liaison JSON:

  1. Ceci est une nouvelle fonctionnalité dans ASP.NET MVC 3 (voir « Améliorations JavaScript et AJAX »).
  2. Les chaînes de l’object JSON (‘X’, ‘Y’, ‘Str’ et ‘Enabled’) doivent correspondre aux propriétés de l’object ViewModel.
  3. Les propriétés de l’object ViewModel doivent avoir { get; set; } { get; set; } { get; set; } méthode
  4. Doit spécifier le type de contenu comme «application / json» dans la demande.
  5. Si cela ne fonctionne toujours pas, vérifiez la chaîne JSON pour vous assurer qu’elle est valide.

En savoir plus sur mon post .

J’espère que cela pourra aider!

Le problème était que les propriétés des modèles qui figuraient dans la liste n’avaient pas de get / set sur leurs propriétés publiques. En d’autres termes, la liaison JSON automatique de MVC3 ne fonctionne que sur les propriétés d’object qui ont get et set.

Cela ne liera pas:

 public ssortingng Str; 

Cela va lier:

 public ssortingng Str { get; set; } 

C’est étrange. Je suis incapable de reproduire votre comportement. Voici ma configuration (ASP.NET MVC 3 RTM):

Modèle:

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

Manette:

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

Vue:

 @{ ViewBag.Title = "Home Page"; }  

En exécutant cette alerte "hi" et à l’intérieur de l’action Save , tout est correctement initialisé.

Et juste pour l’enregistrement, ce qui ne fonctionne pas sont les dictionnaires. J’ai ouvert un ticket sur le problème.

J’ai eu un problème similaire et j’ai constaté que pour un object complexe, les valeurs numériques manquaient. Ils venaient comme des zéros. c’est à dire

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

était reçu par le contrôleur MVC en tant qu’object Person où les propriétés étaient renseignées sous Name=John et Age=0 .

J’ai ensuite fait de la valeur Age en Javascript pour être une chaîne …

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

Et ça s’est bien passé …

C’est parce que les classeurs MVC sont un peu sucer. Cependant, ils fonctionnent très bien si toutes les valeurs JSON sont transmises sous forme de chaîne.

En JS si vous faites cela

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

Il évaluera à 1 pas à 1.0

Donc, lorsque vous l’envoyez au serveur, il essaiera de se lier à un flottant de ce nom et ne le trouvera pas puisqu’il est arrivé à 1 au lieu de 1.0. C’est très boiteux et fou que les ingénieurs MS ne proposent pas de solution par défaut. Je trouve que si vous liez tout, les liaisons sont assez intelligentes pour trouver des choses.

Donc, avant d’envoyer les données par-dessus, exécutez-les via un ssortingngifier qui convertira également toutes les valeurs en chaînes.

Toutes les réponses précédentes m’ont permis de résoudre le problème similaire. J’ai dû POST x-www-form-urlencoding au lieu de application/json (option par défaut si le paramètre contentType est manquant) pour pouvoir passer __RequestVerificationToken et faire face simultanément à un problème lorsque les propriétés d’object du tableau ne lient pas leurs valeurs. La manière de résoudre le problème consiste à comprendre le travail interne du modèle de classeur MVC.

Donc, fondamentalement, lorsque vous devez fournir un jeton de vérification, vous êtes limité par l’atsortingbut de validation. Et vous devez fournir le jeton comme paramètre et non comme une partie de l’object JSON que vous envoyez. Si vous n’utilisez pas ValidateAntiForgeryToken , vous pourriez vous entendre avec JSON.ssortingngify. Mais si vous voulez, vous ne pourriez pas passer le jeton.

J’ai reniflé le trafic à backend lorsque ContentType était x-www-form-urlencoding et j’ai remarqué que mon tableau d’objects complexes était sérialisé en quelque chose comme ça: klo[0][Count]=233&klo[0][Blobs]=94 . Ce tableau faisait initialement partie d’un object racine, disons un modèle. Cela ressemblait à ceci: model.klo = [{ Count: 233, Blobs: 94}, ...] .

Au niveau du backend, cette propriété klo était klo par le classeur MVC avec le même nombre d’éléments que celui que j’ai envoyé. Mais ces éléments eux-mêmes n’ont pas obtenu de valeurs pour leurs propriétés.

SOLUTION

Pour gérer cela, j’ai exclu la propriété klo de l’object modèle du côté client. Dans la fonction ajax j’ai écrit ce 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; } 

La fonction transforme le tableau d'objects complexes en une forme reconnue par MVC-liant. La forme est klo[0].Count=233&klo[0].Blobs=94 .