Передать массив в действие mvc через AJAX

124

Я пытаюсь передать массив (или IEnumerable) int через AJAX в действие MVC, и мне нужна небольшая помощь.

javascript

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {...

и действие контроллера

public ActionResult MyAction(IEnumerable<int> arrayOfValues )

На данный момент запрос отформатирован как

controller/MyAction?_=1301503418429&arrayOfValues[]=491&arrayOfValues[]=368&arrayOfValues[]=235&arrayOfValues[]=437

Так что я почти у цели, если снять квадратные скобки, я получу правильный ответ. Как мне передать этот массив в свой get, чтобы контроллер мог распознать, что это такое?

Большое спасибо за вашу помощь

Дейв

Дейв
источник

Ответы:

149

Установите для традиционного свойства значение true перед вызовом get. то есть:

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 
Chandu
источник
3
Спасибо! не могли бы вы описать различия между традиционным и нетрадиционным ajax? Я хотел бы лучше понять, что я делаю с остальной частью моего приложения.
Tom Beech
5
вы также можете добавить традиционные настройки к одному вызову. Тогда на остальных это не повлияет
Gluip
1
Это правильный ответ, но если вы предпочитаете установить «традиционный» для однократного вызова, проверьте ответ @RionWilliams. Голосуют оба. Спасибо!
kzfabi
@Tom Beech Начиная с jQuery 1.4, метод $ .param () рекурсивно сериализует глубокие объекты для соответствия современным языкам сценариев и средам, таким как PHP и Ruby on Rails. Вы можете отключить эту функцию глобально, установив jQuery.ajaxSettings.traditional = true;
Алексей Шевелев
Ни один из этих ответов у меня не сработал (возможно, потому, что мой контроллер был контроллером API?), Но я нашел свое решение в следующем SO-ответе: stackoverflow.com/a/11100414/1751792
Lopsided
119

В прошлом у меня были проблемы при попытке выполнить POST (не уверен, что это именно то, что вы делаете, но я вспоминаю, что при передаче массива в традиционное значение должно быть установлено значение true .

 var arrayOfValues = new Array();

 //Populate arrayOfValues 
 $.ajax({ 
      type: "POST",
      url: "<%= Url.Action("MyAction","Controller")%>",
      traditional: true,
      data: { 'arrayOfValues': arrayOfValues }              
 });
Рион Уильямс
источник
4
Это намного лучше, чем просто слепо устанавливать его глобально в файле web.config, как предлагают некоторые. У другого есть свой набор хороших случаев, но ваш должен быть решением по умолчанию.
Panzercrisis
Это просто отправка данных в качестве параметра в ActionResult, вызовет ли он код внутри ActionResult? Например, если есть код для вставки массива значений в базу данных, будет ли этот код работать?
Саурабй
Это решило именно то, что мне было нужно. Мои массивы продолжали возвращаться как null в моем контроллере, пока я не добавил это и не получил их в своем контроллере, например: IEnumerable <string> array
SeanMC
52

Довольно поздний, но отличный от уже представленных здесь ответ:

Если вместо этого $.ajaxвы хотите использовать сокращенные функции $.getили $.post, вы можете передавать массивы следующим образом:


Сокращение GET

var array = [1, 2, 3, 4, 5];
$.get('/controller/MyAction', $.param({ data: array }, true), function(data) {});


// Action Method
public void MyAction(List<int> data)
{
    // do stuff here
}

Сокращение POST

var array = [1, 2, 3, 4, 5];
$.post('/controller/MyAction', $.param({ data: array }, true), function(data) {});


// Action Method
[HttpPost]
public void MyAction(List<int> data)
{
    // do stuff here
}


Ноты:

  • Логический параметр в $.paramпредназначен для traditionalсвойства, которое ДОЛЖНО быть, trueчтобы это работало .
загвоздка
источник
2
Спасибо за отзыв о традиционной собственности. Я не мог понять, почему мой параметр C # был нулевым. Я обнаружил, что тип int [] также будет работать в методе C # Action.
Дэн Рэндольф
9

У вас должно получиться отлично:

$.ajax({
   url: 'controller/myaction',
   data: JSON.stringify({
      myKey: myArray
   }),
   success: function(data) { /* Whatever */ }
});

Тогда ваш метод действий будет таким:

public ActionResult(List<int> myKey)
{
    // Do Stuff
}

Для вас это выглядит так, как будто вам просто нужно преобразовать свои значения в строку. JSONValueProvider в MVC преобразует это обратно в IEnumerable для вас.

Tejs
источник
Спасибо за ответ, но я думаю, что мне нужно установить традиционное значение true. Проголосовали, так как я думаю, что это тоже сработает.
Дэйв
9

Ответ на использование «традиционного» варианта правильный. Я просто предоставляю дополнительную информацию для тех, кто хочет узнать больше.

Из документации jQuery:

Начиная с jQuery 1.8, метод $ .param () больше не использует jQuery.ajaxSettings.traditional в качестве настройки по умолчанию и по умолчанию будет иметь значение false.

Вы также можете прочитать больше здесь: http://michaelsync.net/2012/04/05/tips-asp-net-mvc-javascriptserializer-3-questions-and-3-answers и http://haacked.com/archive /2008/10/23/model-binding-to-a-list.aspx

НТН

Том Геркен
источник
2

ЕСЛИ ВСЕ ОСТАЛЬНОЕ ТЕРПИТ НЕУДАЧУ...

Ни один из других ответов здесь не решил мою проблему. Я пытался выполнить вызов метода GET из JavaScript в контроллер веб-API MVC и отправить массив целых чисел в качестве параметра в этом запросе. Я пробовал все решения здесь, но все же параметр на моем контроллере приближался к NULL (или NULL для пользователей VB).

В конце концов я нашел свое решение в другом сообщении SO , и на самом деле оно было действительно простым: просто добавьте [FromUri]аннотацию перед параметром массива в контроллере ( мне также пришлось сделать вызов, используя «традиционный» параметр AJAX, чтобы избежать аннотаций в скобках ). Ниже приведен фактический код, который я использовал в своем приложении.


Подпись контроллера:

Подпись контроллера ПРИМЕЧАНИЕ: аннотация на C # будет [FromUri]


JavaScript:

$.get('/api/InventoryApi/GetBalanceField', $.param({productIds: [42], inventoryFormId: 5493, inventoryBalanceType: 'Beginning'},true)).done(function(data) {console.log(data);});

Фактическая строка URL:

http://randomhostname/api/InventoryApi/GetBalanceField?productIds=42&inventoryFormId=5493&inventoryBalanceType=Beginning
кривобокий
источник
2

Здесь немного поздно, но я мог бы использовать решение SNag в $ .ajax (). Вот код, если это кому-то поможет:

var array = [1, 2, 3, 4, 5];

$.ajax({
    type: "GET",
    url: '/controller/MyAction',
    data: $.param({ data: array}, true),
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
    },
    error: function (x, y, z) {
    }
});

// Action Method
public void MyAction(List<int> data)
{
    // do stuff here
}
Сакет
источник
1

Если вы переходите на ASP.NET Core MVC из .Net Framework MVC, как и я, все немного изменилось. Вызов ajax должен быть на необработанном объекте с использованием stringify, поэтому вместо передачи данных { vals: arrayOfValues }он должен быть JSON.stringify(arrayOfValues)следующим:

$.ajax({
   url: 'controller/myaction',
   data: JSON.stringify(arrayOfValues),
   success: function(data) { /* Whatever */ }
});

Другое изменение, внесенное в ASP.NET Core, - предотвращение подделки межсайтовых запросов, поэтому для вызовов действия MVC из метода ajax [FromBody]атрибут должен применяться к параметру действия следующим образом:

public ActionResult MyAction([FromBody] IEnumerable<int> arrayOfValues )
Майкл Армитаж
источник
Спасибо, это было невероятно полезно после того, как каждая другая перестановка способов отправки данных не удалась!
NibblyPig
0

Если вы используете ASP.NET Core MVC и вам нужно обрабатывать квадратные скобки (вместо того, чтобы использовать «традиционный» вариант jQuery), единственный вариант, который я нашел, - это вручную создать IEnumerableметод контроллера.

string arrayKey = "p[]=";
var pArray = HttpContext.Request.QueryString.Value
    .Split('&')
    .Where(s => s.Contains(arrayKey))
    .Select(s => s.Substring(arrayKey.Length));
x5657
источник
0

Я работаю с asp.net core 2.2 и jquery, и мне нужно отправить сложный объект («основной класс») из представления в контроллер с простыми полями данных и некоторыми массивами.
Как только я добавил массив в определение "основного класса" С # (см. Ниже) и отправил (правильно заполненный) массив через ajax (сообщение), весь объект в контроллере стал нулевым.
Во-первых, я подумал, что причиной моего вызова ajax было отсутствие «традиционного: истина», но это не так.
В моем случае причиной было определение в "основном классе" С #.
В «основном классе» у меня было:

public List<EreignisTagNeu> oEreignistageNeu { get; set; }

и EreignisTagNeu был определен как:

public class EreignisTagNeu
{
 public int iHME_Key { get; set; } 
}

Мне пришлось изменить определение в «основном классе» на:

 public List<int> oEreignistageNeu { get; set; }

Теперь это работает.
Итак ... мне кажется, что у ядра asp.net есть проблема (с сообщением), если список для массива не полностью определен в «основном классе».
Примечание. В моем случае это работает с «традиционным: истинным» или без него для вызова ajax.

FredyWenger
источник
-3

Вам нужно преобразовать массив в строку:

//arrayOfValues = [1, 2, 3];  
$.get('/controller/MyAction', { arrayOfValues: "1, 2, 3" }, function (data) {...

это работает даже в форме int, long или string

public ActionResult MyAction(int[] arrayOfValues )
dr.Crow
источник
Это даже неправильный синтаксис для отправки массива на сервер. Вы просто передаете объект и предполагаете, что это массив, чего никогда не будет с тем, что вы предоставили, то есть STRING.
Twister1002