65 votes

Poster un tableau d'objets via JSON à ASP.Net MVC3

Je cherche une solution pour envoyer un tableau d'objets à 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.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
}

Le résultat de ce POST :

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

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 JsonValueProvider de MVC3 ne fonctionne pas pour les objets complexes. Comment faire pour que cela fonctionne ? Dois-je modifier le JsonValueProvider MVC3 existant et le corriger ? Si oui, comment puis-je l'atteindre et le remplacer dans un projet MVC3 ?

Questions connexes sur StackOverflow que j'ai déjà traitées en vain :

Asp.net Mvc Ajax Json (post Array) Utilise MVC2 et l'ancien encodage basé sur le formulaire - cette approche échoue avec un objet qui contient un tableau d'objets (JQuery ne parvient pas à l'encoder correctement).

Poster un tableau d'objets complexes avec JSON, JQuery à ASP.NET MVC Controller Utilise un hack que j'aimerais éviter, où le contrôleur reçoit une simple chaîne de caractères qu'il désérialise manuellement lui-même, plutôt que d'utiliser le framework.

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

Comment poster un tableau d'objets complexes avec JSON, jQuery à ASP.NET MVC Controller ? Ce pauvre type a dû écrire un JsonFilter juste pour analyser un tableau. Un autre hack que je préférerais éviter.

Alors, comment faire pour que ça arrive ?

43voto

stack247 Points 645

En plus de { get; set; } Voici quelques-unes des conditions de la prise en charge de la liaison JSON :

  1. Il s'agit d'une nouvelle fonctionnalité d'ASP.NET MVC 3 (voir " Améliorations de JavaScript et AJAX ").
  2. Les chaînes de l'objet JSON ('X', 'Y', 'Str' et 'Enabled') doivent correspondre aux propriétés de l'objet ViewModel.
  3. Les propriétés de l'objet ViewModel doivent avoir { get; set; } méthode.
  4. Il faut spécifier le type de contenu "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.

Plus d'informations sur mon poste .

J'espère que cela vous aidera !

30voto

Chris Moschini Points 7278

Le problème était que les propriétés des modèles qui étaient 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'objets qui ont un get et un set.

Cela ne se lie pas :

public string Str;

Cela va lier :

public string Str { get; set; }

29voto

Darin Dimitrov Points 528142

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

Modèle :

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; }
}

Contrôleur :

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Save(ListViewModel list)
    {
        return Json(list);
    }
}

Voir :

@{
    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>

Exécution de ces alertes "hi" et à l'intérieur de la Save action tout est correctement initialisé.

Et pour mémoire, ce qui ne fonctionne pas, ce sont les dictionnaires. J'ai déjà a ouvert un ticket sur la question.

3voto

Dev Points 21

J'ai eu un problème similaire, et j'ai constaté que pour un objet complexe, les valeurs numériques étaient manquées. Elles arrivaient sous forme de zéros. Par exemple.

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

était reçu par le contrôleur MVC en tant qu'objet Personne où les propriétés étaient remplies en tant que Name=John y Age=0 .

J'ai ensuite fait en sorte que la valeur Age en Javascript soit une chaîne de caractères... c'est à dire

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

Et ça, ça passe très bien...

0voto

Chris Stephens Points 499

C'est parce que les classeurs MVC craignent un peu. Cependant, ils fonctionnent assez bien si toutes les valeurs JSON sont envoyées sous forme de chaîne.

En JS, si vous faites ceci

var myObject = {thisNumber:1.6};

myObject.thisNumber=myObject.thisNumber-.6;

Elle sera évaluée à 1 et non à 1.0.

Ainsi, lorsque vous l'avez envoyé au serveur, il essaiera de se lier à un flotteur de ce nom et il ne le trouvera pas puisqu'il est arrivé sous la forme 1 au lieu de 1.0. C'est vraiment nul et fou que les ingénieurs de MS n'aient pas trouvé une solution par défaut à ce problème. Je trouve que si vous mettez tout en chaîne, les bindings sont assez intelligents pour trouver les choses.

Avant d'envoyer les données, il faut donc les faire passer par un stringificateur qui convertira également toutes les valeurs en chaînes de caractères.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X