web-dev-qa-db-fra.com

Manière correcte d'utiliser AJAX Post dans jQuery pour passer le modèle à partir d'une vue MVC3 fortement typée

Je suis un programmeur web novice, alors pardonnez-moi si une partie de mon "jargon" n'est pas correcte. J'ai un projet utilisant ASP.NET utilisant le framework MVC3.

Je travaille sur une vue d'administrateur où l'administrateur modifiera une liste d'équipements. L’une des fonctions est un bouton de "mise à jour" que je souhaite utiliser avec jQuery pour modifier de manière dynamique l’entrée de la page Web après l’envoi d’un message au contrôleur MVC.

Je présume que cette approche est "sûre" dans un contexte d'administration unique où il y a peu d'inquiétude de la synchronisation de la page Web avec la base de données.

J'ai créé une vue fortement typée et espérais transmettre les données du modèle au contrôle MVC à l'aide d'une publication AJAX.

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

Je vais utiliser l'exemple de code de l'article 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; }
}

Manette:

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

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

script dans la vue:

<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 d'utiliser ce qui précède. 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?

Devrais-je m'inquiéter d'exposer les informations du modèle?

99
John Stone

Vous pouvez ignorer 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");
    }
});
71
Craig M

J'ai trouvé 3 façons d'implémenter ceci:

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 manières:

1) Chaîne de requête:

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

Les données ici sont une chaîne.

"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 ici sont 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 ici sont une chaîne JSON sérialisée. Notez que le nom doit correspondre au nom du paramètre sur le serveur!

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

Voici comment cela a fonctionné pour moi:

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

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

ce que vous avez est bien - cependant, pour économiser du texte, vous pouvez simplement utiliser pour vos données

 
 données: $ ('# formId'). serialize () 
 

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

8

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 quiconque dans ma situation. J'ai essayé les solutions ci-dessus, mais elles ne fonctionnaient pas 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";
    }
}

- Notez les bibliothèques using System.Web.Mvc et using System.Web.Mvc.Filters, pas les bibliothèques http (je pense que c'est l'une des choses qui a changé avec MVC v5. -

Ensuite, appliquez simplement le filtre [ValidateJSONAntiForgeryHeader] à votre action (ou contrôleur) et celui-ci devrait être appelé correctement.

Dans ma page de mise en page juste au-dessus de </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
});
0
blubberbo