Przekazywanie listy obiektów do metody kontrolera MVC przy użyciu jQuery Ajax

113

Próbuję przekazać tablicę obiektów do metody kontrolera MVC przy użyciu funkcji ajax () jQuery. Kiedy dostaję się do metody kontrolera C # PassThing (), argument „things” ma wartość null. Próbowałem tego przy użyciu typu listy jako argumentu, ale to też nie działa. Co ja robię źle?

<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; }
    }
}
Zimorodek
źródło
3
Twoje dane są ciągiem znaków, ale twoja metoda akceptuje tablicę. Zmień metodę, aby akceptowała ciąg, a następnie deserializuj ją w ramach metody.
Bob Horn
2
Twój kod jest poprawny. Przetestowałem to i zadziałało przy użyciu MVC 4. Proszę podać więcej danych, aby to rozgryźć.
Diego
To świetna rzecz, ale co zrobić, jeśli potrzebujesz nie tylko listy ciągów do przekazania, ale musisz dołączyć oddzielny identyfikator powiązany z listą ciągów? Na przykład identyfikator grupy, lista grup pod identyfikatorem grupy.
Nathan McKaskle

Odpowiedzi:

188

Korzystając z sugestii NickW, udało mi się to uruchomić, używając things = JSON.stringify({ 'things': things });Oto pełny kod.

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

Nauczyłem się z tego dwóch rzeczy:

  1. Ustawienia contentType i dataType są absolutnie niezbędne w funkcji ajax (). Nie zadziała, jeśli ich brakuje. Dowiedziałem się tego po wielu próbach i błędach.

  2. Aby przekazać tablicę obiektów do metody kontrolera MVC, po prostu użyj formatu JSON.stringify ({'things': things}).

Mam nadzieję, że to pomoże komuś innemu!

Zimorodek
źródło
8
Miałem ten sam problem i dodanie contentType naprawiło go. Dzięki!
Rochelle C
9
Dwie rzeczy do zapamiętania: JSON.stringify i określenie „contentType”.
dinesh ygv
Crud. Nadal nie działa dla mnie. mój adres URL żądania to http://localhost:52459/Sales/completeSale?itemsInCart=[{"ItemId":1,"Quantity":"1","Price":3.5}]i Sales.completeSalejest public ActionResult completeSale(ItemInCart[] itemsInCart), oznaczony jako HttpGet.
abalter
3
z jakiegokolwiek powodu musiałem po prostu użyćdata: JSON.stringify(things),
Rob Scott
1
dataTypeto nie jest konieczne. Jeśli zostanie pominięty, funkcja ajax rozwiąże to na podstawie zwróconych danych
32

Nie mógłbyś po prostu tego zrobić?

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

... i oznacz swoje działanie za pomocą

[HttpPost]
public void PassThings(IEnumerable<Thing> things)
{
    // do stuff with things here...
}
bagno latarniowe
źródło
3
To powinna być najlepsza odpowiedź. W tym przypadku nie należy używać JSON.stringify
To nie działa dla mnie .. Używam [HttpPost] public int SaveResults (model List <ShortDetail>) {} i $ .post ("@ Url.Action (" SaveResults "," Maps ")", {model: dataItems}, funkcja (wynik) {});
Samra,
2
U mnie zadziałało. Absolutnie najlepsza odpowiedź. Nie wiem, dlaczego implementacja Halcyon nie zadziałała. Wywołano funkcję PassThings, ale zmienna wejściowa „things” była pusta, nawet jeśli została wypełniona w javascript tuż przed wywołaniem.
Leonardo Daga
12

Używam aplikacji sieci Web .Net Core 2.1 i nie mogę tutaj uzyskać ani jednej odpowiedzi, aby działała. Otrzymałem pusty parametr (jeśli w ogóle wywołano metodę) lub błąd serwera 500. Zacząłem bawić się każdą możliwą kombinacją odpowiedzi i w końcu uzyskałem efekt pracy.

W moim przypadku rozwiązanie wyglądało następująco:

Skrypt - stringify oryginalnej tablicy (bez używania nazwanej właściwości)

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

W metodzie kontrolera użyj [FromBody]

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

Niepowodzenia obejmują:

  • Nazwanie treści

    data: {content: nodes}, // Błąd serwera 500

  • Brak contentType = Błąd serwera 500

Uwagi

  • dataTypenie jest potrzebny, pomimo tego, co mówią niektóre odpowiedzi, ponieważ jest używany do dekodowania odpowiedzi (więc nie ma znaczenia dla przykładów żądań tutaj).
  • List<Thing> działa również w metodzie kontrolera
Gone Coding
źródło
10

Na to wszystko mam doskonałą odpowiedź: wypróbowałem tak wiele rozwiązań, których w końcu nie mogłem sobie poradzić, poniżej znajdziesz szczegółową odpowiedź:

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

Kontroler

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
źródło
Powinieneś mieć więcej pozytywnych głosów: tradycyjny: prawda jest zalecanym sposobem na stronie Jquery
DFTR,
7

Jedynym sposobem, aby to zadziałało, jest przekazanie JSON jako ciągu, a następnie deserializacja za pomocą JavaScriptSerializer.Deserialize<T>(string input) , co jest dość dziwne, jeśli jest to domyślny deserializator dla MVC 4.

Mój model ma zagnieżdżone listy obiektów, a najlepsze, co mogłem uzyskać przy użyciu danych JSON, to najwyższa lista zawierająca poprawną liczbę elementów, ale wszystkie pola w elementach były puste.

Takie rzeczy nie powinny być takie trudne.

    $.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);
bardziej naglący żart
źródło
Aby to zadziałało, ściśle przestrzegaj formatu wywołania Ajax.
Graham Laight
4

To działa kod dla twojego zapytania, możesz go użyć.

Kontroler

    [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
źródło
2

Zawijanie listy obiektów innym obiektem zawierającym właściwość pasującą do nazwy parametru, którego oczekuje kontroler MVC, działa. Ważnym elementem jest opakowanie wokół listy obiektów.

$(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; }
}
Chuligan
źródło
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
źródło
Wypróbuj ten kod do przekazywania listy obiektów modelu przy użyciu ajax. Model reprezentuje IList <Model>. Użyj IList <Model> w kontrolerze, aby pobrać wartości.
Athul Nalupurakkal
0

Jeśli korzystasz z interfejsu API sieci Web ASP.NET, po prostu prześlij data: JSON.stringify(things).

Twój kontroler powinien wyglądać mniej więcej tak:

public class PassThingsController : ApiController
{
    public HttpResponseMessage Post(List<Thing> things)
    {
        // code
    }
}
FleGMan
źródło
0

Modyfikacja z @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
      }
Minhajul Islam
źródło
0

Co zrobiłem, próbując wysłać dane z kilku wybranych wierszy w DataTable do akcji MVC:

HTML Na początku strony:

@Html.AntiForgeryToken()

(wyświetlany jest tylko wiersz, powiąż z modelu):

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

Przycisk uruchamiający funkcję JavaScript:

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

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

Akcja MVC:

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

I MODEL w 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; }
 }

WNIOSEK:

Przyczyna BŁĘDU:

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

Atrybut Is: [ValidateAntiForgeryToken]dla akcji MVCStartWorkflow

Rozwiązanie w połączeniu Ajax:

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

Aby wysłać Listę obiektów należy uformować dane jak w przykładzie (obiekt listy wypełniającej) oraz:

data: {model: list},

type: "post",

łaskawy
źródło
0

Jak dla mnie to działa dobrze:

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

Z „ContentType” wielką literą „C”.

Myksomatoza
źródło