Passaggio di un elenco di oggetti in un metodo controller MVC utilizzando jQuery Ajax


113

Sto cercando di passare un array di oggetti in un metodo controller MVC utilizzando la funzione ajax () di jQuery. Quando entro nel metodo controller PassThing () C #, l'argomento "cose" è nullo. L'ho provato usando un tipo di Elenco per l'argomento, ma nemmeno questo funziona. Che cosa sto facendo di sbagliato?

<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; }
    }
}


3
I tuoi dati sono una stringa, ma il tuo metodo accetta un array. Modificare il metodo per accettare una stringa, quindi deserializzarla all'interno del metodo.
Bob Horn

2
Il tuo codice è corretto. L'ho testato e ha funzionato usando MVC 4. Fornisci più dati per capirlo.
Diego

Questa è un'ottima cosa, ma cosa succede se non è necessario solo un elenco di stringhe da passare ma è necessario includere un ID separato associato all'elenco di stringhe? Quindi come, ID gruppo, elenco di gruppi sotto ID gruppo.
Nathan McKaskle

Risposte:


188

Usando il suggerimento di NickW, sono stato in grado di farlo funzionare usando things = JSON.stringify({ 'things': things });Ecco il codice completo.

$(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; }
}

Ci sono due cose che ho imparato da questo:

  1. Le impostazioni contentType e dataType sono assolutamente necessarie nella funzione ajax (). Non funzionerà se mancano. L'ho scoperto dopo molti tentativi ed errori.

  2. Per passare un array di oggetti a un metodo del controller MVC, utilizza semplicemente il formato JSON.stringify ({'things': things}).

Spero che questo aiuti qualcun'altro!


8
Avevo lo stesso problema e l'aggiunta di contentType lo ha risolto. Grazie!
Rochelle C

9
Due cose da notare: JSON.stringify e specificando "contentType".
dinesh ygv

Crud. Ancora non funziona per me. l'URL della mia richiesta è http://localhost:52459/Sales/completeSale?itemsInCart=[{"ItemId":1,"Quantity":"1","Price":3.5}]ed Sales.completeSaleè public ActionResult completeSale(ItemInCart[] itemsInCart)annotato come HttpGet.
abalter

3
per qualsiasi motivo ho dovuto usare solodata: JSON.stringify(things),
Rob Scott il

1
dataTypenon è necessario. Se viene omesso, la funzione ajax funzionerà in base ai dati di ritorno

32

Non potresti semplicemente farlo?

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.');
   });

... e contrassegna la tua azione con

[HttpPost]
public void PassThings(IEnumerable<Thing> things)
{
    // do stuff with things here...
}

3
Questa dovrebbe essere la risposta migliore. JSON.stringify non deve essere utilizzato in questo caso

Questo non funziona per me .. Sto usando [HttpPost] public int SaveResults (List <ShortDetail> model) {} e $ .post ("@ Url.Action (" SaveResults "," Maps ")", {model: dataItems}, funzione (risultato) {});
Samra

2
Ha funzionato per me. Assolutamente la migliore risposta. Non so perché l'implementazione di Halcyon non abbia funzionato. La funzione PassThings è stata invocata ma la variabile di input "things" era vuota anche se era stata compilata nel javascript appena prima della chiamata.
Leonardo Daga


12

Sto usando un'applicazione Web .Net Core 2.1 e non sono riuscito a ottenere una singola risposta qui per funzionare. Ho ricevuto un parametro vuoto (se il metodo è stato chiamato affatto) o un errore del server 500. Ho iniziato a giocare con ogni possibile combinazione di risposte e finalmente ho ottenuto un risultato di lavoro.

Nel mio caso la soluzione era la seguente:

Script: stringa l'array originale (senza utilizzare una proprietà denominata)

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

E nel metodo controller, usa [FromBody]

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

I guasti includono:

  • Denominazione del contenuto

    dati: {contenuto: nodi}, // Errore del server 500

  • Non avendo il contentType = Errore del server 500

Appunti

  • dataTypenon è necessario, nonostante ciò che dicono alcune risposte, in quanto viene utilizzato per la decodifica della risposta (quindi non rilevante per gli esempi di richiesta qui).
  • List<Thing> funziona anche nel metodo controller

10

Ho una risposta perfetta per tutto questo: ho provato tante soluzioni non in grado di riuscire finalmente a gestirmi, per favore trova la risposta dettagliata di seguito:

       $.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);
            }
        });

controler

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
  }

Dovresti avere più voti positivi: tradizionale: true è il modo consigliato sul sito web di Jquery
DFTR

7

L'unico modo per farlo funzionare è passare il JSON come stringa e quindi deserializzarlo utilizzando JavaScriptSerializer.Deserialize<T>(string input) , il che è piuttosto strano se questo è il deserializzatore predefinito per MVC 4.

Il mio modello ha elenchi di oggetti annidati e il meglio che potrei ottenere utilizzando i dati JSON è l'elenco più in alto per contenere il numero corretto di elementi, ma tutti i campi negli elementi erano nulli.

Questo genere di cose non dovrebbe essere così 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);

Per fare in modo che funzioni, segui attentamente il formato della chiamata Ajax.
Graham Laight

4

Questo codice funziona per la tua query, puoi usarlo.

controler

    [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");
   }
   });

2

Il wrapping dell'elenco di oggetti con un altro oggetto contenente una proprietà che corrisponde al nome del parametro previsto dal controller MVC funziona. La parte importante è il wrapper attorno all'elenco degli oggetti.

$(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; }
}

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");
    }
});

Prova questo codice per passare l'elenco degli oggetti del modello usando ajax. Model rappresenta IList <Model>. Utilizzare IList <Model> nel controller per ottenere i valori.
Athul Nalupurakkal

0

Se stai usando l'API Web ASP.NET, dovresti semplicemente passare data: JSON.stringify(things).

E il tuo controller dovrebbe assomigliare a questo:

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

0

Modifica da @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
      }

0

Cosa ho fatto quando ho provato a inviare alcuni dati da diverse righe selezionate in DataTable all'azione MVC:

HTML All'inizio di una pagina:

@Html.AntiForgeryToken()

(viene mostrata solo una riga, associazione dal modello):

 @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>
                }

Pulsante che avvia la funzione JavaScript:

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

Funzione 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();
                    }
                });
            }
        }

Azione MVC:

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

E MODELLO in 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; }
 }

CONCLUSIONE:

Il motivo dell'ERRORE:

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

È attributo: [ValidateAntiForgeryToken]per l'azione MVCStartWorkflow

Soluzione nella chiamata Ajax:

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

Per inviare Elenco di oggetti è necessario formare dati come nell'esempio (oggetto elenco di popolamento) e:

dati: {model: list},

tipo: "post",


0

Ecco come funziona bene per me:

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);
    }
});

Con "ContentType" nella "C" maiuscola.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.