106 votes

Comment utiliser AJAX Post en jquery pour passer le modèle depuis une vue MVC3 fortement typée ?

Je suis un programmeur web novice, alors veuillez me pardonner si mon "jargon" n'est pas correct. J'ai un projet utilisant ASP.NET avec le cadre MVC3.

Je travaille sur une vue d'administration où l'administrateur modifiera une liste d'équipements. L'une des fonctions est un bouton de "mise à jour". Je veux utiliser jquery pour modifier dynamiquement l'entrée sur la page web après avoir envoyé un message au contrôleur MVC.

Je suppose que cette approche est "sûre" dans un cadre d'administration unique où le risque de désynchronisation entre la page Web et la base de données est minime.

J'ai créé une vue qui est fortement typée et j'espérais transmettre les données du modèle au contrôle MVC en utilisant un post AJAX.

Dans le post suivant, j'ai trouvé quelque chose qui est similaire à ce que je cherche à faire : JQuery Ajax et ASP.NET MVC3 provoquant des paramètres nuls

Je vais utiliser l'exemple de code du post ci-dessus.

Modèle :

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Contrôleur :

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

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

script dans View :

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

Je n'ai pas encore eu l'occasion de les utiliser. Mais je me demandais si c'était la "meilleure" méthode pour renvoyer les données du modèle au contrôle MVC en utilisant AJAX ?

Dois-je craindre d'exposer les informations du modèle ?

178voto

Jazaret Points 1444

J'ai trouvé 3 façons de mettre cela en œuvre :

Classe C# :

public class AddressInfo {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Action :

[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
    return Json(new { success = true });
}

JavaScript vous pouvez le faire de trois façons :

1) Chaîne de requête :

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serialize(),
    type: 'POST',
});

Les données sont ici une chaîne de caractères.

"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"

2) Tableau d'objets :

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serializeArray(),
    type: 'POST',
});

Les données sont ici un tableau de paires clé/valeur :

=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]

3) JSON :

$.ajax({
      url: '/en/Home/Check',
      data: JSON.stringify({ addressInfo:{//missing brackets
          Address1: $('#address1').val(),
          Address2: $('#address2').val(),
          City: $('#City').val(),
          State: $('#State').val(),
          ZipCode: $('#ZipCode').val()}}),
      type: 'POST',
      contentType: 'application/json; charset=utf-8'
});

Les données sont ici une chaîne sérialisée JSON. Notez que le nom doit correspondre au nom du paramètre dans le serveur !

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'

1 votes

Je viens de tomber sur cette réponse formidable et complète qui a résolu des questions que je ne savais pas encore avoir. +1, merci !

0 votes

2 était ce que je cherchais. Cela devrait être la réponse.

0 votes

EDIT : a dû utiliser data: $('input, textarea, select').serialize(), pour que le mien fonctionne.

75voto

Craig M Points 3011

Vous pouvez sauter la déclaration var et le stringify. Sinon, cela fonctionnera très bien.

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: {
        Address1: "423 Judy Road",
        Address2: "1001",
        City: "New York",
        State: "NY",
        ZipCode: "10301",
        Country: "USA"
    },
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
        alert(data.success);
    },
    error: function () {
        alert("error");
    }
});

0 votes

Merci de m'avoir signalé ce léger ajustement. L'exposition de la structure du modèle pose-t-elle des problèmes de sécurité ?

0 votes

Rien de flagrant ne me semble être un problème de sécurité. Si vous êtes vraiment inquiet à ce sujet, vous pouvez toujours créer un modèle personnalisé de liaison du côté mvc.

10 votes

Cela a échoué pour moi. J'ai dû utiliser JSON.stringify( { ... } ) pour que l'appel fonctionne dans MVC5.

12voto

Sanchitos Points 2263

C'est comme ça que ça a marché pour moi :

$.post("/Controller/Action", $("#form").serialize(), function(json) {       
        // handle response
}, "json");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}

8voto

Adam Tuliper - MSFT Points 22478

Ce que vous avez est bien - cependant, pour éviter de taper, vous pouvez simplement utiliser pour vos données

data: $('#formId').serialize()

voir http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ pour les détails, la syntaxe est assez basique.

0 votes

Afin d'utiliser la fonction de sérialisation, je crois comprendre que chaque membre de la classe doit être utilisé dans un objet de formulaire. Si cela est correct, je suis peut-être SOL.

1 votes

Ah oui... si ce n'est pas le cas vous ne pouvez pas utiliser serialize. vous pouvez toujours manipuler le DOM cependant et créer un formulaire avec ces éléments et le sérialiser - mais... il serait probablement plus propre d'avoir juste les champs tapés manuellement alors.

0 votes

@TahaRehmanSiddiqui serialize fonctionne en effet dans IE, qu'est-ce qui ne fonctionne pas ? Obtenez-vous une erreur ?

0voto

blubberbo Points 1025

Si vous utilisez MVC 5, lisez cette solution !

Je sais que la question portait spécifiquement sur MVC 3, mais je suis tombé sur cette page avec MVC 5 et je voulais poster une solution pour tous ceux qui se trouvent dans ma situation. J'ai essayé les solutions ci-dessus, mais elles n'ont pas fonctionné pour moi, le filtre d'action n'a jamais été atteint et je ne pouvais pas comprendre pourquoi. J'utilise la version 5 dans mon projet et je me suis retrouvé avec le filtre d'action suivant :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SydHeller.Filters
{
    public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
            if (clientToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
            }

            string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
            if (serverToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
            }

            System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
        }

        private const string KEY_NAME = "__RequestVerificationToken";
    }
}

-- Prenez note de la using System.Web.Mvc y using System.Web.Mvc.Filters et non le http (je pense que c'est l'une des choses qui a changé avec MVC v5. --

Ensuite, il suffit d'appliquer le filtre [ValidateJSONAntiForgeryHeader] à votre action (ou contrôleur) et elle devrait être appelée correctement.

Dans ma page de mise en page, juste au-dessus </body> J'ai @AntiForgery.GetHtml();

Enfin, dans ma page Razor, je fais l'appel ajax comme suit :

var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
  type: "POST",
  url: serviceURL,
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  data: requestData,
  headers: {
     "__RequestVerificationToken": formForgeryToken
  },
     success: crimeDataSuccessFunc,
     error: crimeDataErrorFunc
});

1 votes

Vous récupérez toutes les valeurs de vos formulaires manuellement ? Pourquoi pas data: $("#the-form").serialize() ?

1 votes

@Sinjai Il faudrait que je regarde à nouveau mon code, mais je crois que je fais d'autres traitements là-dedans aussi. ".serialize()" fonctionnerait également si vous n'avez besoin que des valeurs d'entrée.

0 votes

Pas de soucis, j'étais juste curieux.

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