Passer une liste d'objets dans une méthode de contrôleur MVC à l'aide de jQuery Ajax

113

J'essaie de passer un tableau d'objets dans une méthode de contrôleur MVC en utilisant la fonction ajax () de jQuery. Quand j'entre dans la méthode du contrôleur PassThing () C #, l'argument «choses» est nul. J'ai essayé cela en utilisant un type de liste pour l'argument, mais cela ne fonctionne pas non plus. Qu'est-ce que je fais mal?

<script type="text/javascript">
    $(document).ready(function () {
        var things = [
            { id: 1, color: 'yellow' },
            { id: 2, color: 'blue' },
            { id: 3, color: 'red' }
        ];

        $.ajax({
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            type: 'POST',
            url: '/Xhr/ThingController/PassThing',
            data: JSON.stringify(things)
        });
    });
</script>

public class ThingController : Controller
{
    public void PassThing(Thing[] things)
    {
        // do stuff with things here...
    }

    public class Thing
    {
        public int id { get; set; }
        public string color { get; set; }
    }
}
Alcyon
la source
3
Vos données sont une chaîne, mais votre méthode accepte un tableau. Modifiez votre méthode pour accepter une chaîne, puis désérialisez-la dans la méthode.
Bob Horn
2
Votre code est correct. Je l'ai testé et cela a fonctionné avec MVC 4. Veuillez fournir plus de données pour le comprendre.
Diego
C'est génial, mais que se passe-t-il si vous avez besoin non seulement d'une liste de chaînes à transmettre, mais également d'inclure un identifiant distinct associé à la liste de chaînes? Donc, comme, identifiant de groupe, liste des groupes sous identifiant de groupe.
Nathan McKaskle

Réponses:

188

En utilisant la suggestion de NickW, j'ai pu faire fonctionner cela en utilisant things = JSON.stringify({ 'things': things });Voici le code complet.

$(document).ready(function () {
    var things = [
        { id: 1, color: 'yellow' },
        { id: 2, color: 'blue' },
        { id: 3, color: 'red' }
    ];      

    things = JSON.stringify({ 'things': things });

    $.ajax({
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        type: 'POST',
        url: '/Home/PassThings',
        data: things,
        success: function () {          
            $('#result').html('"PassThings()" successfully called.');
        },
        failure: function (response) {          
            $('#result').html(response);
        }
    }); 
});


public void PassThings(List<Thing> things)
{
    var t = things;
}

public class Thing
{
    public int Id { get; set; }
    public string Color { get; set; }
}

J'ai appris deux choses:

  1. Les paramètres contentType et dataType sont absolument nécessaires dans la fonction ajax (). Cela ne fonctionnera pas s'ils sont manquants. J'ai découvert cela après de nombreux essais et erreurs.

  2. Pour transmettre un tableau d'objets à une méthode de contrôleur MVC, utilisez simplement le format JSON.stringify ({'things': things}).

J'espère que ça aidera quelqu'un d'autre!

Alcyon
la source
8
J'avais le même problème et l'ajout du contentType l'a corrigé. Merci!
Rochelle C
9
Deux choses à noter: JSON.stringify et la spécification de 'contentType'.
dinesh ygv
Crud. Je ne travaille toujours pas pour moi. mon URL de demande est http://localhost:52459/Sales/completeSale?itemsInCart=[{"ItemId":1,"Quantity":"1","Price":3.5}]et Sales.completeSaleest public ActionResult completeSale(ItemInCart[] itemsInCart), annotée en tant que HttpGet.
abalter le
3
pour une raison quelconque, je devais simplement utiliserdata: JSON.stringify(things),
Rob Scott
1
dataTypen'est pas nécessaire. S'il est omis, la fonction ajax fonctionnera en fonction des données de retour
32

Tu ne pourrais pas faire ça?

var things = [
    { id: 1, color: 'yellow' },
    { id: 2, color: 'blue' },
    { id: 3, color: 'red' }
];
$.post('@Url.Action("PassThings")', { things: things },
   function () {
        $('#result').html('"PassThings()" successfully called.');
   });

... et marquez votre action avec

[HttpPost]
public void PassThings(IEnumerable<Thing> things)
{
    // do stuff with things here...
}
lanterne
la source
3
Cela devrait être la meilleure réponse. Le JSON.stringify ne doit pas être utilisé dans ce cas
Cela ne fonctionne pas pour moi .. J'utilise [HttpPost] public int SaveResults (List <ShortDetail> model) {} et $ .post ("@ Url.Action (" SaveResults "," Maps ")", {model: dataItems}, fonction (résultat) {});
Samra
2
Cela a fonctionné pour moi. Absolument la meilleure réponse. Je ne sais pas pourquoi l'implémentation Halcyon n'a pas fonctionné. La fonction PassThings a été appelée mais la variable d'entrée 'things' était vide même si elle était remplie dans le javascript juste avant l'appel.
Leonardo Daga
12

J'utilise une application Web .Net Core 2.1 et je n'ai pas pu obtenir une seule réponse ici pour fonctionner. J'ai soit un paramètre vide (si la méthode a été appelée du tout) soit une erreur de serveur 500. J'ai commencé à jouer avec toutes les combinaisons possibles de réponses et j'ai finalement obtenu un résultat satisfaisant.

Dans mon cas, la solution était la suivante:

Script - stringify le tableau d'origine (sans utiliser une propriété nommée)

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

Et dans la méthode du contrôleur, utilisez [FromBody]

    [HttpPost]
    public IActionResult NewBranch([FromBody]IEnumerable<Thing> things)
    {
        return Ok();
    }

Les échecs incluent:

  • Nommer le contenu

    data: {content: nodes}, // Erreur serveur 500

  • Ne pas avoir le contentType = Erreur serveur 500

Remarques

  • dataTypen'est pas nécessaire, malgré ce que disent certaines réponses, car cela est utilisé pour le décodage de la réponse (donc pas pertinent pour les exemples de demande ici).
  • List<Thing> fonctionne également dans la méthode du contrôleur
Codage terminé
la source
10

J'ai la réponse parfaite à tout cela: j'ai essayé tellement de solutions que je n'ai pas réussi à gérer moi-même, veuillez trouver la réponse détaillée ci-dessous:

       $.ajax({
            traditional: true,
            url: "/Conroller/MethodTest",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify( 
               [
                { id: 1, color: 'yellow' },
                { id: 2, color: 'blue' },
                { id: 3, color: 'red' }
                ]),
            success: function (data) {
                $scope.DisplayError(data.requestStatus);
            }
        });

Contrôleur

public class Thing
{
    public int id { get; set; }
    public string color { get; set; }
}

public JsonResult MethodTest(IEnumerable<Thing> datav)
    {
   //now  datav is having all your values
  }
Veera Induvasi
la source
Vous devriez avoir plus de votes positifs: traditionnel: true est la méthode recommandée sur le site Web de Jquery
DFTR
7

La seule façon dont je pourrais faire fonctionner cela est de passer le JSON en tant que chaîne, puis de le désérialiser à l'aide JavaScriptSerializer.Deserialize<T>(string input), ce qui est assez étrange si c'est le désérialiseur par défaut pour MVC 4.

Mon modèle comporte des listes d'objets imbriquées et le mieux que je puisse obtenir en utilisant les données JSON est la liste la plus élevée pour contenir le nombre correct d'éléments, mais tous les champs des éléments étaient nuls.

Ce genre de chose ne devrait pas être si difficile.

    $.ajax({
        type: 'POST',
        url: '/Agri/Map/SaveSelfValuation',
        data: { json: JSON.stringify(model) },
        dataType: 'text',
        success: function (data) {

    [HttpPost]
    public JsonResult DoSomething(string json)
    {
        var model = new JavaScriptSerializer().Deserialize<Valuation>(json);
plaisanterie plus urgente
la source
Pour que cela fonctionne, suivez de près le format de l'appel Ajax.
Graham Laight
4

C'est du code de travail pour votre requête, vous pouvez l'utiliser.

Contrôleur

    [HttpPost]
    public ActionResult save(List<ListName> listObject)
    {
    //operation return
    Json(new { istObject }, JsonRequestBehavior.AllowGet); }
    }

javascript

  $("#btnSubmit").click(function () {
    var myColumnDefs = [];
    $('input[type=checkbox]').each(function () {
        if (this.checked) {
            myColumnDefs.push({ 'Status': true, 'ID': $(this).data('id') })
        } else {
            myColumnDefs.push({ 'Status': false, 'ID': $(this).data('id') })
        }
    });
   var data1 = { 'listObject': myColumnDefs};
   var data = JSON.stringify(data1)
   $.ajax({
   type: 'post',
   url: '/Controller/action',
   data:data ,
   contentType: 'application/json; charset=utf-8',
   success: function (response) {
    //do your actions
   },
   error: function (response) {
    alert("error occured");
   }
   });
sach4all
la source
2

Enveloppant votre liste d'objets avec un autre objet contenant une propriété qui correspond au nom du paramètre attendu par le contrôleur MVC fonctionne. L'important étant le wrapper autour de la liste d'objets.

$(document).ready(function () {
    var employeeList = [
        { id: 1, name: 'Bob' },
        { id: 2, name: 'John' },
        { id: 3, name: 'Tom' }
    ];      

    var Employees = {
      EmployeeList: employeeList
    }

    $.ajax({
        dataType: 'json',
        type: 'POST',
        url: '/Employees/Process',
        data: Employees,
        success: function () {          
            $('#InfoPanel').html('It worked!');
        },
        failure: function (response) {          
            $('#InfoPanel').html(response);
        }
    }); 
});


public void Process(List<Employee> EmployeeList)
{
    var emps = EmployeeList;
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}
Voyou
la source
1
     var List = @Html.Raw(Json.Encode(Model));
$.ajax({
    type: 'post',
    url: '/Controller/action',
    data:JSON.stringify({ 'item': List}),
    contentType: 'application/json; charset=utf-8',
    success: function (response) {
        //do your actions
    },
    error: function (response) {
        alert("error occured");
    }
});
Athul Nalupurakkal
la source
Essayez ce code pour transmettre la liste des objets de modèle à l'aide d'ajax. Le modèle représente l'IList <Model>. Utilisez IList <Model> dans le contrôleur pour obtenir les valeurs.
Athul Nalupurakkal le
0

Si vous utilisez l'API Web ASP.NET, vous devez simplement passer data: JSON.stringify(things).

Et votre manette devrait ressembler à ceci:

public class PassThingsController : ApiController
{
    public HttpResponseMessage Post(List<Thing> things)
    {
        // code
    }
}
FleGMan
la source
0

Modification de @veeresh i

 var data=[

                        { id: 1, color: 'yellow' },
                        { id: 2, color: 'blue' },
                        { id: 3, color: 'red' }
                        ]; //parameter
        var para={};
        para.datav=data;   //datav from View


        $.ajax({
                    traditional: true,
                    url: "/Conroller/MethodTest",
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    data:para,
                    success: function (data) {
                        $scope.DisplayError(data.requestStatus);
                    }
                });

In MVC



public class Thing
    {
        public int id { get; set; }
        public string color { get; set; }
    }

    public JsonResult MethodTest(IEnumerable<Thing> datav)
        {
       //now  datav is having all your values
      }
Islam Minhajul
la source
0

Ce que j'ai fait en essayant d'envoyer des données à partir de plusieurs lignes sélectionnées dans l'action DataTable vers MVC:

HTML Au début d'une page:

@Html.AntiForgeryToken()

(juste une ligne est affichée, lier à partir du modèle):

 @foreach (var item in Model.ListOrderLines)
                {
                    <tr data-orderid="@item.OrderId" data-orderlineid="@item.OrderLineId" data-iscustom="@item.IsCustom">
                        <td>@item.OrderId</td>
                        <td>@item.OrderDate</td>
                        <td>@item.RequestedDeliveryDate</td>
                        <td>@item.ProductName</td>
                        <td>@item.Ident</td>
                        <td>@item.CompanyName</td>
                        <td>@item.DepartmentName</td>
                        <td>@item.ProdAlias</td>
                        <td>@item.ProducerName</td>
                        <td>@item.ProductionInfo</td>
                    </tr>
                }

Bouton qui lance la fonction JavaScript:

 <button class="btn waves-effect waves-light btn-success" onclick="ProcessMultipleRows();">Start</button>

Fonction JavaScript:

  function ProcessMultipleRows() {
            if ($(".dataTables_scrollBody>tr.selected").length > 0) {
                var list = [];
                $(".dataTables_scrollBody>tr.selected").each(function (e) {
                    var element = $(this);
                    var orderid = element.data("orderid");
                    var iscustom = element.data("iscustom");
                    var orderlineid = element.data("orderlineid");
                    var folderPath = "";
                    var fileName = "";

                    list.push({ orderId: orderid, isCustomOrderLine: iscustom, orderLineId: orderlineid, folderPath: folderPath, fileName : fileName});
                });

                $.ajax({
                    url: '@Url.Action("StartWorkflow","OrderLines")',
                    type: "post", //<------------- this is important
                    data: { model: list }, //<------------- this is important
                    beforeSend: function (xhr) {//<--- This is important
                      xhr.setRequestHeader("RequestVerificationToken",
                      $('input:hidden[name="__RequestVerificationToken"]').val());
                      showPreloader();
                    },
                    success: function (data) {

                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {

                    },
                     complete: function () {
                         hidePreloader();
                    }
                });
            }
        }

Action MVC:

[HttpPost]
[ValidateAntiForgeryToken] //<--- This is important
public async Task<IActionResult> StartWorkflow(IEnumerable<WorkflowModel> model)

Et MODÈLE en C #:

public class WorkflowModel
 {
        public int OrderId { get; set; }
        public int OrderLineId { get; set; }
        public bool IsCustomOrderLine { get; set; }
        public string FolderPath { get; set; }
        public string FileName { get; set; }
 }

CONCLUSION:

La raison de l'ERREUR:

"Failed to load resource: the server responded with a status of 400 (Bad Request)"

Est attribut: [ValidateAntiForgeryToken]pour l'action MVCStartWorkflow

Solution dans l'appel Ajax:

  beforeSend: function (xhr) {//<--- This is important
                      xhr.setRequestHeader("RequestVerificationToken",
                      $('input:hidden[name="__RequestVerificationToken"]').val());
                    },

Pour envoyer une liste d'objets, vous devez former des données comme dans l'exemple (objet de liste de remplissage) et:

données: {model: list},

type: "post",

chatouilleux
la source
0

Voici comment cela fonctionne bien pour moi:

var things = [
    { id: 1, color: 'yellow' },
    { id: 2, color: 'blue' },
    { id: 3, color: 'red' }
];

$.ajax({
    ContentType: 'application/json; charset=utf-8',
    dataType: 'json',
    type: 'POST',
    url: '/Controller/action',
    data: { "things": things },
    success: function () {
        $('#result').html('"PassThings()" successfully called.');
    },
    error: function (response) {
        $('#result').html(response);
    }
});

Avec "ContentType" en majuscule "C".

Myxomatose
la source