Передача списка объектов в метод контроллера MVC с использованием jQuery Ajax


113

Я пытаюсь передать массив объектов в метод контроллера MVC с помощью функции jQuery ajax (). Когда я перехожу к методу контроллера PassThing () C #, аргумент «вещи» равен нулю. Я пробовал это, используя тип List в качестве аргумента, но это тоже не работает. Что я делаю не так?

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

Вы можете попробовать JavaScriptSerializer.Deserialize Method (String, Type)
jk.

3
Ваши данные представляют собой строку, но ваш метод принимает массив. Измените свой метод, чтобы он принимал строку, затем десериализуйте ее внутри метода.
Боб Хорн

2
Ваш код правильный. Я тестировал его, и он работал с использованием MVC 4. Пожалуйста, предоставьте больше данных, чтобы понять это.
Diego

Это замечательный материал, но что, если вам нужен не просто список строк для передачи, а нужно включить отдельный идентификатор, связанный со списком строк? Например, идентификатор группы, список групп под идентификатором группы.
Натан МакКаскл

Ответы:


188

Используя предложение NickW, я смог заставить это работать, используя things = JSON.stringify({ 'things': things });вот полный код.

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

Из этого я извлек две вещи:

  1. Параметры contentType и dataType абсолютно необходимы в функции ajax (). Без них ничего не получится. Я выяснил это после долгих проб и ошибок.

  2. Чтобы передать массив объектов методу контроллера MVC, просто используйте формат JSON.stringify ({'things': things}).

Надеюсь, это поможет кому-то другому!


8
У меня была такая же проблема, и добавление contentType исправило ее. Спасибо!
Rochelle C

9
Обратите внимание на две вещи: JSON.stringify и указание contentType.
dinesh ygv 07

Crud. У меня все еще не работает. мой запрос URL является http://localhost:52459/Sales/completeSale?itemsInCart=[{"ItemId":1,"Quantity":"1","Price":3.5}]и Sales.completeSaleбудет public ActionResult completeSale(ItemInCart[] itemsInCart), аннотированный как HttpGet.
abalter

3
по какой-то причине мне пришлось просто использоватьdata: JSON.stringify(things),
Роб Скотт

1
dataTypeне обязательно. Если его опустить, функция ajax будет работать с ним на основе возвращаемых данных

32

Не могли бы вы просто сделать это?

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

... и отметьте свое действие значком

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

3
Это должен быть лучший ответ. JSON.stringify не следует использовать в этом случае

У меня это не работает ... Я использую [HttpPost] public int SaveResults (List <ShortDetail> model) {} и $ .post ("@ Url.Action (" SaveResults "," Maps ")", {model: dataItems}, функция (результат) {});
Samra

2
У меня это сработало. Абсолютно лучший ответ. Я не знаю, почему реализация Halcyon не сработала. Функция PassThings была вызвана, но входная переменная «вещи» была пустой, даже если она была заполнена в javascript непосредственно перед вызовом.
Леонардо Дага

13

Форматирование ваших данных может быть проблемой. Попробуйте одно из этих:

data: '{ "things":' + JSON.stringify(things) + '}',

Или (из раздела Как я могу отправить массив строк в контроллер ASP.NET MVC без формы? )

var postData = { things: things };
...
data = postData

Ваш код близок, но он не работает. Мне удалось заставить код работать благодаря вашему предложению. Смотрите мой ответ выше.
Halcyon

12

Я использую веб-приложение .Net Core 2.1 и не могу получить здесь ни одного ответа. У меня либо пустой параметр (если метод вообще был вызван), либо ошибка сервера 500. Я начал экспериментировать со всевозможными комбинациями ответов и наконец получил рабочий результат.

В моем случае решение было следующим:

Сценарий - преобразование исходного массива в строку (без использования именованного свойства)

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

А в методе контроллера используйте [FromBody]

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

Сбои включают:

  • Именование контента

    data: {content: nodes}, // Ошибка сервера 500

  • Отсутствие contentType = Ошибка сервера 500

Ноты

  • dataTypeне требуется, несмотря на то, что говорится в некоторых ответах, поскольку он используется для декодирования ответа (поэтому не имеет отношения к примерам запросов здесь).
  • List<Thing> также работает в методе контроллера

10

У меня есть идеальный ответ на все это: я пробовал так много решений, которые, наконец, не смогли заставить себя справиться, пожалуйста, найдите подробный ответ ниже:

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

У вас должно быть больше голосов: традиционный: true - это рекомендуемый способ на веб-сайте JQuery
DFTR

7

Единственный способ заставить это работать - передать JSON в виде строки, а затем десериализовать ее с помощью JavaScriptSerializer.Deserialize<T>(string input), что довольно странно, если это десериализатор по умолчанию для MVC 4.

Моя модель имеет вложенные списки объектов, и лучшее, что я мог получить, используя данные JSON, - это самый верхний список, в котором содержится правильное количество элементов, но все поля в элементах были пустыми.

Такие вещи не должны быть такими сложными.

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

Чтобы это сработало, внимательно следите за форматом вызова Ajax.
Graham Laight

4

Это рабочий код вашего запроса, вы можете его использовать.

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

Обертывание вашего списка объектов другим объектом, содержащим свойство, которое соответствует имени параметра, ожидаемого контроллером MVC, работает. Важный бит - это оболочка вокруг списка объектов.

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

Попробуйте этот код для передачи списка объектов модели с помощью ajax. Модель представляет собой IList <Model>. Используйте IList <Model> в контроллере, чтобы получить значения.
Athul Nalupurakkal

0

Если вы используете веб-API ASP.NET, вам нужно просто пройти data: JSON.stringify(things).

И ваш контроллер должен выглядеть примерно так:

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

0

Модификация от @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

Что я сделал при попытке отправить некоторые данные из нескольких выбранных строк в DataTable в действие MVC:

HTML В начале страницы:

@Html.AntiForgeryToken()

(отображается только строка, привязка к модели):

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

Кнопка, запускающая функцию JavaScript:

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

Функция 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();
                    }
                });
            }
        }

Действие MVC:

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

И МОДЕЛЬ на 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; }
 }

ВЫВОД:

Причина ОШИБКИ:

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

Атрибут Is: [ValidateAntiForgeryToken]для действия MVCStartWorkflow

Решение в вызове Ajax:

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

Чтобы отправить Список объектов, вам необходимо сформировать данные как в примере (заполнение объекта списка) и:

данные: {модель: список},

тип: "сообщение",


0

Вот как это работает для меня:

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

С «ContentType» в заглавной «C».

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.