Подання списку об’єктів у метод контролера MVC за допомогою jQuery Ajax


113

Я намагаюся передати масив об'єктів у метод контролера MVC за допомогою функції ajax () jQuery. Коли я потрапляю в метод контролера C # PassThing (), аргумент "речі" є нульовим. Я спробував це, використовуючи тип списку для аргументу, але і це не працює. Що я роблю неправильно?

<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. Будь ласка, надайте більше даних, щоб зрозуміти це.
Дієго

Це чудові речі, але що робити, якщо вам потрібно не просто список рядків для передачі, а потрібно включити окремий ідентифікатор, пов'язаний зі списком рядків? Таким чином, ідентифікатор групи, список груп під ідентифікатором групи.
Натан Маккаскл

Відповіді:


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 ({'речі': речі}).

Я сподіваюся, що це допомагає комусь іншому!


8
У мене була така ж проблема, і додавання contentType виправлено її. Дякую!
Рошель C

9
Дві речі, які слід зазначити: JSON.stringify та вказівка ​​"contentType".
dinesh ygv

Сирий. Ще не працює для мене. 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 (Список <ShortDetail> модель) {} та $ .post ("@ Url.Action (" SaveResults "," Maps ")", {model: dataItems}, функція (результат) {});
Самра

2
Це працювало для мене. Абсолютно найкраща відповідь. Я не знаю, чому реалізація Halcyon не спрацювала. Функція PassThings викликалася, але вхідна змінна "речі" була порожньою, навіть якщо вона була заповнена в JavaScript безпосередньо перед викликом.
Леонардо Дага

13

Форматування даних, що може бути проблемою. Спробуйте будь-що з цього:

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

Або (з Як я можу розмістити масив рядків на ASP.NET MVC Controller без форми? )

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

Ваш код близький, але він не працює. Мені вдалося змусити код працювати завдяки вашій пропозиції. Дивіться мою відповідь вище.
Гельсіон

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

Невдачі включають:

  • Названня вмісту

    дані: {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);
            }
        });

Контролер

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
  }

У вас повинно бути більше оновлень: традиційний: правда є рекомендованим способом на веб-сайті 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.
Грем Лайт

4

Це робочий код для вашого запиту, ви можете ним скористатися.

Контролер

    [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> в контролері, щоб отримати значення.
Атул Налупураккал

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

Є атрибутом: [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.