53 votes

ASP.NET MVC Comment passer un objet JSON de la vue au contrôleur comme paramètre ?

J'ai un objet JSON complexe qui est envoyé à la vue sans aucun problème (comme indiqué ci-dessous) mais je n'arrive pas à trouver comment sérialiser ces données en un objet .NET lorsqu'elles sont renvoyées au contrôleur par un appel AJAX. Les détails des différentes parties sont ci-dessous.

   var ObjectA = {
        "Name": 1,
        "Starting": new Date(1221644506800),

        "Timeline": [
            {
                "StartTime": new Date(1221644506800),
                "GoesFor": 200

            }
            ,
            {
                "StartTime": new Date(1221644506800),
                "GoesFor": 100

            }

        ]
    };

Je ne suis pas sûr de la façon dont cet objet peut être transmis à une méthode de contrôleur, j'ai cette méthode ci-dessous où l'objet Timelines reflète l'objet JS ci-dessus en utilisant les propriétés.

public JsonResult Save(Timelines person)

Le jQuery que j'utilise est :

        var encoded = $.toJSON(SessionSchedule);

        $.ajax({
            url: "/Timeline/Save",
            type: "POST",
            dataType: 'json',
            data: encoded,
            contentType: "application/json; charset=utf-8",
            beforeSend: function() { $("#saveStatus").html("Saving").show(); },
            success: function(result) {
                alert(result.Result);
                $("#saveStatus").html(result.Result).show();
            }
        });

J'ai vu cette question qui est similaire, mais pas tout à fait la même car je n'utilise pas de formulaires pour manipuler les données. http://stackoverflow.com/questions/267707/how-to-pass-complex-type-using-json-to-asp-net-mvc-controller

J'ai également vu des références à l'utilisation d'un 'JsonFilter' pour désérialiser manuellement le JSON, mais je me demandais s'il y avait un moyen de le faire nativement à travers ASP.NET MVC ? Ou quelles sont les meilleures pratiques pour transmettre des données de cette manière ?

51voto

DaRKoN_ Points 4098

Edit :

Cette méthode ne devrait plus être nécessaire avec l'arrivée de MVC 3, car elle sera gérée automatiquement - http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx


Vous pouvez utiliser cet ObjectFilter :

    public class ObjectFilter : ActionFilterAttribute {

    public string Param { get; set; }
    public Type RootType { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext) {
        if ((filterContext.HttpContext.Request.ContentType ?? string.Empty).Contains("application/json")) {
            object o =
            new DataContractJsonSerializer(RootType).ReadObject(filterContext.HttpContext.Request.InputStream);
            filterContext.ActionParameters[Param] = o;
        }

    }
}

Vous pouvez ensuite l'appliquer aux méthodes de votre contrôleur comme suit :

    [ObjectFilter(Param = "postdata", RootType = typeof(ObjectToSerializeTo))]
    public JsonResult ControllerMethod(ObjectToSerializeTo postdata) { ... }

Ainsi, si le type de contenu de l'article est "application/json", le système entre en action et fait correspondre les valeurs à l'objet du type que vous spécifiez.

13voto

Craig Stuntz Points 95965

Vous dites "Je n'utilise pas de formulaire pour manipuler les données". Mais vous faites un POST. Par conséquent, vous utilisez en fait un formulaire, même s'il est vide.

L'élément $.ajax dataType indique à jQuery le type de serveur à utiliser. retourner et non ce que vous transmettez. POST ne peut transmettre qu'un formulaire. jQuery convertira les données en paires clé/valeur et le passer comme chaîne de requête. Dans la documentation :

Données à envoyer au serveur. Elles sont converties en chaîne de requête, si elles ne sont pas déjà une chaîne. Elle est ajoutée à l url pour les requêtes GET. Voir l'option processData pour empêcher ce traitement automatique. automatique. Les objets doivent être des paires Clé/Valeur paires. Si la valeur est un tableau, jQuery sérialise plusieurs valeurs avec la même même clé, c'est-à-dire que {foo :["bar1", "bar2"]} devient '&foo=bar1&foo=bar2'.

Par conséquent :

  1. Vous ne transmettez pas de JSON au serveur. Vous passez JSON à jQuery.
  2. La liaison de modèle se produit de la même manière que dans tout autre cas.

11voto

Robert Koritnik Points 45499

Une approche différente avec un simple plugin jQuery

Bien que les réponses à cette question soient attendues depuis longtemps, je vais tout de même poster une solution intéressante que j'ai trouvée il y a quelque temps et qui permet de simplifier les opérations suivantes envoyer un JSON complexe à Asp.net MVC les actions du contrôleur afin qu'elles soient liées par le modèle à n'importe quel paramètre de type fort.

Ce plugin dates de soutien aussi bien, donc ils sont convertis à leur DateTime homologue sans problème.

Vous pouvez trouver tous les détails dans mon blog post où j'examine le problème et fournit le code nécessaire pour y parvenir.

Tout ce que vous avez à faire est d'utiliser ce plugin du côté client. Une requête Ajax ressemblerait à ceci :

$.ajax({
    type: "POST",
    url: "SomeURL",
    data: $.toDictionary(yourComplexJSONobject),
    success: function() { ... },
    error: function() { ... }
});

Mais ce n'est qu'une partie du problème. Maintenant, nous sommes en mesure de renvoyer un JSON complexe au serveur, mais comme il sera lié par un modèle à un type complexe qui peut avoir des attributs de validation sur les propriétés, les choses peuvent échouer à ce stade. J'ai un solution pour ce problème également . Ma solution tire parti de la fonctionnalité Ajax de jQuery où les résultats peuvent être positifs ou erronés (comme indiqué dans le code supérieur). Ainsi, lorsque la validation échoue, error serait appelée comme elle est censée l'être.

4voto

swilliams Points 19415

Il y a le JavaScriptSerializer que vous pouvez aussi utiliser. Cela vous permettra de désérialiser le json vers un objet .NET. Il existe une classe générique Deserialize<T> Cependant, vous devrez faire en sorte que l'objet .NET ait une signature similaire à celle de l'objet javascript. En outre, il existe également un DeserializeObject qui ne fait qu'un simple object . Vous pouvez ensuite utiliser la réflexion pour obtenir les propriétés dont vous avez besoin.

Si votre contrôleur prend un FormCollection et vous n'avez pas ajouté d'autres éléments à la liste. data le json doit être dans form[0] :

public ActionResult Save(FormCollection forms) {
  string json = forms[0];
  // do your thing here.
}

2voto

Alex Ford Points 15277

Cette réponse fait suite à la réponse de DaRKoN_ qui utilisait le filtre d'objet :

[ObjectFilter(Param = "postdata", RootType = typeof(ObjectToSerializeTo))]
    public JsonResult ControllerMethod(ObjectToSerializeTo postdata) { ... }

J'avais un problème pour trouver comment envoyer plusieurs paramètres à une méthode d'action et faire en sorte que l'un d'entre eux soit un objet json et l'autre une simple chaîne de caractères. Je suis nouveau dans MVC et j'avais juste oublié que j'avais déjà résolu ce problème avec des vues non-ajaxées.

Ce que je ferais si j'avais besoin, disons, de deux objets différents sur une vue. Je créerais une classe ViewModel. Donc disons que j'ai besoin de l'objet personne et de l'objet adresse, je ferais ce qui suit :

public class SomeViewModel()
{
     public Person Person { get; set; }
     public Address Address { get; set; }
}

Puis je lierais la vue à SomeViewModel. Vous pouvez faire la même chose avec JSON.

[ObjectFilter(Param = "jsonViewModel", RootType = typeof(JsonViewModel))] // Don't forget to add the object filter class in DaRKoN_'s answer.
public JsonResult doJsonStuff(JsonViewModel jsonViewModel)
{
     Person p = jsonViewModel.Person;
     Address a = jsonViewModel.Address;
     // Do stuff
     jsonViewModel.Person = p;
     jsonViewModel.Address = a;
     return Json(jsonViewModel);
}

Ensuite, dans la vue, vous pouvez utiliser un appel simple avec JQuery comme ceci :

var json = { 
    Person: { Name: "John Doe", Sex: "Male", Age: 23 }, 
    Address: { Street: "123 fk st.", City: "Redmond", State: "Washington" }
};

$.ajax({
     url: 'home/doJsonStuff',
     type: 'POST',
     contentType: 'application/json',
     dataType: 'json',
     data: JSON.stringify(json), //You'll need to reference json2.js
     success: function (response)
     {
          var person = response.Person;
          var address = response.Address;
     }
});

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