web-dev-qa-db-fra.com

Utiliser jQuery pour publier des données dans la méthode d'action MVC

J'essaie de publier des données en utilisant l'action jQuery Ajax to MVC en utilisant l'approche ci-dessous. Mais à l'intérieur du contrôleur, toutes les propriétés du modèle sont toujours null. Pas sûr de ce que je manque ici.

.CSHTML  

<form id="MyForm">
<input name="PersonName" type="text" />
<input name="Address" type="text" />
<select name="States" multiple="multiple">
    <option value="TX">Texas</option>
    <option value="OK">Oklahoma</option>
    <option value="OH">Ohio</option>
</select>
<select name="Status">
    <option value="1">Active</option>
    <option value="2">Deleted</option>
    <option value="3">Pending</option>
</select>
<input type="button" value="Save" id="Save" />

JavaScript  

$(function () {
$("#Save").click(function (e) {
    var dataToPost = $("#MyForm").serialize()
    $.ajax(
    {
        type: "POST",
        data: JSON.stringify(dataToPost),
        url: "Working/Save",
        contentType: 'application/json; charset=utf-8'
    })
  })
})

Manette  

public class WorkingController : Controller
{
    // GET: Working
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Save(WorkingModel model)
    {
        // All model properties are null here????

        return Json("Success");
    }
 }

Modèle  

public class WorkingModel
{
    public string PersonName { get; set; }
    public string Address { get; set; }
    public string[] States { get; set; }
    public string Status { get; set; }
}

EDIT1
J'ai ajouté le modèle ci-dessus. Voici les données sérialisées et les données JSON stringify lorsque je clique sur enregistrer. 

Données sérialisées

"PersonName=Foo&Address=123+Test+Drive&States=TX&Status=1"

Après JSON.Stringify

"\"PersonName=Foo&Address=123+Test+Drive&States=TX&Status=1\""

J'ai essayé d'ajouter l'attribut HttpPost et l'attribut [FromBody] sans aucune chance.

Je ne pense pas devoir modifier le type de retour de ActionResult à JsonResult.

De plus, l'URL est correcte car le débogueur effectue une frappe à l'intérieur de la méthode d'action où je peux QuickWatch les propriétés du modèle.

Notez que cela fonctionne si je crée un objet JSON et le poste comme ci-dessous:

var dataToPost = {
    PersonName:'Foo',
    Address: '123 Test Drive',
    State: 'TX',
    Status: 1
 }
5
LP13

Votre code JavaScript/jQuery peut être considérablement simplifié, ce qui pourrait être la meilleure voie à suivre:

$(function () {
    $("#MyForm").on('submit', function (e) {

        e.preventDefault() // prevent the form's normal submission

        var dataToPost = $(this).serialize()

        $.post("Working/Save", dataToPost)
            .done(function(response, status, jqxhr){ 
                // this is the "success" callback
            })
            .fail(function(jqxhr, status, error){ 
                // this is the ""error"" callback
            })
    })
})

Vous devez gérer l'événement onsubmit du formulaire, plutôt que l'événement onclick du bouton - il est possible qu'un élément autre que le bouton provoque la soumission du formulaire. Dans ce cas, nous voulons empêcher le comportement d'envoi par défaut du formulaire, car nous le soumettons avec AJAX.

.serialize() gère déjà correctement le codage du formulaire. Vous n'avez donc pas besoin de coder JSON pour les valeurs du formulaire. Cela est probablement la raison pour laquelle modelbinder ne reconstruit pas le modèle lors du traitement de la demande.

$.post est une fonction d'assistance qui encapsule les tâches de configuration courantes dont vous avez besoin pour $.ajax - la version présentée ici veut que l'URL soit dirigée vers POST, et les données vers POST. Si votre code jQuery est dans un élément de script dans une vue, vous voudrez probablement utiliser l'assistant Url.Action() - il construira l'URL correcte en fonction de vos règles de routage. Si vous choisissez cette voie, vous utiliseriez quelque chose comme:

$.post('@Url.Action("Save", "Working")', dataToPost)

Ensuite, nous gérons la réponse réussie (tout élément avec un code d'état HTTP-200) et la réponse ayant échoué (tout autre élément, en gros) à l'aide des assistants appropriés. Ce que vous faites dans ces aides est à vous.

10
Tieson T.

Je pense que vous devriez soumettre des données de formulaire HTML standard plutôt que des données JSON. Par conséquent, changez les lignes:

data: JSON.stringify(dataToPost),
contentType: 'application/json; charset=utf-8'

à 

data: dataToPost,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'

Remarque: Vous pouvez également omettre la deuxième ligne car il s'agit de la variable contentType par défaut pour $.ajax Selon documentation jQuery .

EDIT 1 Ceci est une réponse à votre commentaire et à votre modification.

Ce que j'essayais de vous dire, c'est que les données envoyées par votre Ajax doivent correspondre à la manière dont vous traitez les données reçues par votre action. La raison pour laquelle les propriétés de votre modèle sont null est que ces deux propriétés ne correspondent pas.

Vous n'avez pas posté le code de votre action. Nous n'avons donc aucune idée de la façon dont vous traitez les données. Maintenant, à partir de votre édition 1, il semble que vous traitez les données reçues sous forme de données JSON, car cela a fonctionné lorsque vous l'avez envoyé. données JSON réelles.

Donc, vous devez faire l'une des deux choses suivantes:

1- Envoyer des données JSON réelles: Le simple fait d'utiliser JSON.stringify ne signifie pas que vos données sont désormais des données JSON appropriées. Comme vous l'avez constaté, JSON.stringify a simplement entouré votre chaîne de guillemets pour en faire une chaîne JSON valide, c'est tout. Mais ce n'est pas ce que votre action attend, elle attend un objet JSON. Pour envoyer un objet JSON, vous devez probablement écrire une fonction prenant les champs de formulaire un par un et construire un objet JSON, puis appeler cette fonction au lieu de JSON.stringify.

2- Envoyer des données de formulaire standard: C'est ce que je suggérais dans ma réponse ci-dessus. Pour que cela fonctionne, supprimez simplement tout le code de votre action qui le traite en tant qu'objet JSON. MVC est conçu pour traiter les données de formulaire standard par défaut, vous n'avez donc pas besoin de traitement supplémentaire. Envoyez-lui simplement des données de formulaire standard et cela fonctionnera.

Remarque: Ajax ne pas doit envoyer/recevoir des données au format JSON. Le format JSON est très utile pour échanger des données dans de nombreux scénarios, mais vous choisissez le format qui convient à votre scénario spécifique. Par exemple, votre action renvoie un objet JSON uniquement pour le résultat suivant: return Json("Success"). Si vous souhaitez uniquement envoyer un résultat simple (succès ou échec), vous pouvez renvoyer une chaîne simple (par exemple, return "Success") ou même un booléen/entier (par exemple, return "True" ou return "1"). Les objets Jason nécessitent un traitement supplémentaire pour être analysés à partir de la chaîne. Bien que ce traitement soit très rapide et efficace, il est encore un peu plus rapide d'analyser et de traiter des types de données simples tels que chaîne, booléen ou entier si vous n'avez pas besoin d'envoyer d'informations supplémentaires.

5
Racil Hilan

je dois juste supprimer le type de contenu de la publication et ne pas la stigmatiser et cela a fonctionné

$(function () {
  $("#Save").click(function (e) {
  var dataToPost = $("#MyForm").serialize()
  $.ajax(
  {
    type: "POST",
    data: dataToPost,
    url: "Working/Save"
  })
 })
})
4
LP13

Déplacez le texte de la réponse précédente vers Pastebin comme je me suis trompé, la réponse est la suivante:

Il suffit de lire votre édition, votre problème est que JSON a l’air drôle: "\" PersonName = Foo & Address = 123 + Test + Lecteur & States = TX & Status = 1\"" Cela ne se traduira pas par WorkingModel.

Ma recommandation est de créer un objet JS personnalisé et de le publier. Je viens de lancer un projet VS MVC et je l’ai fait, tout fonctionne bien :)

$(function() {
    $("#Save").click(function(e) {
        var personName = $("[name='PersonName']").val();
        var address = $("[name='Address']").val();
        var states = $("[name='States']").val();
        var status = $("[name='Status']").val();
        var dataToPost = {
            PersonName: personName,
            Address: address,
            States: states,
            Status: status
        };

        $.ajax(
        {
            type: "POST",
            data: JSON.stringify(dataToPost),
            url: "Save",
            contentType: 'application/json; charset=utf-8'
        });
    });
});

J'espère que cela t'aides!

1
Michael Crook