Przekaż tablicę do akcji mvc przez AJAX

123

Próbuję przekazać tablicę (lub IEnumerable) ints z przez AJAX do akcji MVC i potrzebuję trochę pomocy.

javascript to

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

a akcją kontrolera jest

public ActionResult MyAction(IEnumerable<int> arrayOfValues )

W tej chwili żądanie jest sformatowane jako

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

Jestem prawie na miejscu, jeśli usunę nawiasy kwadratowe, otrzymam poprawną odpowiedź. Jak powinienem przekazać tę tablicę do mojego get, aby kontroler mógł rozpoznać, co to jest?

Wielkie dzięki za Twoją pomoc

Dave

Dave
źródło

Odpowiedzi:

149

Ustaw tradycyjną właściwość na true przed wykonaniem wywołania get. to znaczy:

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 
Chandu
źródło
3
Dziękuję Ci! czy mógłbyś przedstawić różnice między tradycyjnym a nietradycyjnym Ajaxem? chciałbym lepiej zrozumieć, co robię z resztą mojej aplikacji.
Tom Beech
5
możesz także dodać tradycyjne ustawienie do pojedynczego połączenia. Wtedy nie wpłynie to na resztę
Gluip
1
Ta odpowiedź jest poprawna, ale jeśli wolisz ustawić „tradycyjne” dla pojedynczego połączenia, sprawdź odpowiedź @RionWilliams. Głosowanie na obu. Dzięki!
kzfabi
@Tom Beech Począwszy od jQuery 1.4, metoda $ .param () serializuje rekurencyjnie głębokie obiekty, aby dostosować się do nowoczesnych języków skryptowych i struktur, takich jak PHP i Ruby on Rails. Możesz wyłączyć tę funkcję globalnie, ustawiając jQuery.ajaxSettings.traditional = true;
Alexey Shevelyov
Żadna z tych odpowiedzi nie zadziałała dla mnie (może dlatego, że mój kontroler był kontrolerem API?), Ale znalazłem swoje rozwiązanie w następującej odpowiedzi SO: stackoverflow.com/a/11100414/1751792
Lopsided
119

W przeszłości miałem problemy podczas próby wykonania POST (nie jestem pewien, czy to jest dokładnie to, co robisz, ale przypominam sobie, że podczas przekazywania tablicy tradycyjna musi być ustawiona na true .

 var arrayOfValues = new Array();

 //Populate arrayOfValues 
 $.ajax({ 
      type: "POST",
      url: "<%= Url.Action("MyAction","Controller")%>",
      traditional: true,
      data: { 'arrayOfValues': arrayOfValues }              
 });
Rion Williams
źródło
4
Jest to o wiele lepsze niż po prostu ślepe ustawianie go globalnie w pliku web.config, jak sugerują niektórzy. Drugi ma swój własny zestaw dobrych okazji, ale Twój powinien być domyślnym rozwiązaniem.
Panzercrisis
To jest po prostu wysyłanie danych jako parametru do ActionResult, czy wywoła kod Inside ActionResult? Na przykład, jeśli istnieje kod do wstawiania arrayofvalues ​​do bazy danych, czy ten kod będzie działał?
Saurabh
To rozwiązało dokładnie to, czego potrzebowałem. Moje tablice wracały jako null w moim kontrolerze, dopóki nie dodałem tego i nie otrzymałem ich w moim kontrolerze, na przykład: tablica IEnumerable <string>
SeanMC
52

Dość późno, ale inaczej odpowiedź od tych już obecnych tutaj:

Jeśli zamiast tego $.ajaxchciałbyś użyć funkcji skróconych $.getlub $.post, możesz przekazać tablice w ten sposób:


Skrótowe POBIERZ

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
}

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


Uwagi:

  • Parametr boolowski w $.paramjest dla traditionalwłaściwości, która MUSI być, trueaby to zadziałało .
Szkopuł
źródło
2
Dzięki za wskazówkę dotyczącą tradycyjnej nieruchomości. Nie mogłem dowiedzieć się, dlaczego mój parametr C # był zerowy. Odkryłem, że typ „int []” będzie działał również w metodzie Action C #.
Dan Randolph,
9

Powinieneś być w stanie to zrobić dobrze:

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

Wtedy Twoja metoda działania wyglądałaby tak:

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

Wygląda na to, że musisz po prostu zdefiniować wartości. JSONValueProvider w MVC przekonwertuje to z powrotem na IEnumerable dla Ciebie.

Tejs
źródło
Dzięki za odpowiedź, ale wydaje mi się, że muszę ustawić tradycyjne na prawdziwe. Głosowałem za, ponieważ myślę, że to też zadziała.
Dave,
9

Odpowiedź na użycie opcji „tradycyjnej” jest prawidłowa. Podaję tylko dodatkowe informacje dla tych, którzy chcą dowiedzieć się więcej.

Z dokumentacji jQuery:

Od wersji jQuery 1.8 metoda $ .param () nie używa już jQuery.ajaxSettings.traditional jako ustawienia domyślnego i domyślnie przyjmuje wartość false.

Możesz również przeczytać więcej tutaj: http://michaelsync.net/2012/04/05/tips-asp-net-mvc-javascriptserializer-3-questions-and-3-answers i http://haacked.com/archive /2008/10/23/model-binding-to-a-list.aspx

HTH

Tom Gerken
źródło
2

JEŚLI WSZYSTKO INNE ZAWIEDZIE...

Żadna z pozostałych odpowiedzi nie rozwiązała mojego problemu. Próbowałem wykonać wywołanie metody GET z JavaScript do kontrolera interfejsu API sieci Web MVC i wysłać tablicę liczb całkowitych jako parametr w ramach tego żądania. Wypróbowałem tutaj wszystkie rozwiązania, ale nadal parametr na moim kontrolerze zbliżał się do NULL (lub Nic dla użytkowników VB).

W końcu znalazłem swoje rozwiązanie w innym poście SO i było to naprawdę proste: po prostu dodaj [FromUri]adnotację przed parametrem tablicy w kontrolerze ( musiałem również wykonać wywołanie przy użyciu „tradycyjnego” ustawienia AJAX, aby uniknąć adnotacji w nawiasach ). Zobacz poniżej rzeczywisty kod, którego użyłem w mojej aplikacji.


Podpis kontrolera:

Podpis kontrolera UWAGA: Adnotacja w C # byłaby [FromUri]


JavaScript:

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

Rzeczywisty ciąg adresu URL:

http://randomhostname/api/InventoryApi/GetBalanceField?productIds=42&inventoryFormId=5493&inventoryBalanceType=Beginning
Przechylony
źródło
2

Trochę późno tutaj, ale mógłbym użyć rozwiązania SNag dalej w $ .ajax (). Oto kod, gdyby komuś pomógł:

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
}
Saket
źródło
1

Jeśli przeprowadzasz migrację do ASP.NET Core MVC z .Net Framework MVC, tak jak ja, sytuacja nieco się zmieniła. Wywołanie AJAX musi znajdować się w surowym obiekcie przy użyciu stringify, więc zamiast przekazywania danych { vals: arrayOfValues }powinno wyglądać JSON.stringify(arrayOfValues)następująco:

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

Inną zmianą, która została wprowadzona w ASP.NET Core, jest zapobieganie fałszowaniu żądań między lokacjami, więc dla wywołań akcji MVC z metody ajax [FromBody]należy zastosować atrybut do parametru akcji w następujący sposób:

public ActionResult MyAction([FromBody] IEnumerable<int> arrayOfValues )
Michael Armitage
źródło
Dziękuję, było to niezwykle pomocne po tym, jak każda inna kombinacja sposobów wysyłania danych zawiodła!
NibblyPig
0

Jeśli używasz ASP.NET Core MVC i potrzebujesz obsługi nawiasów kwadratowych (zamiast używać opcji „tradycyjnej” jQuery), jedyną opcją, jaką znalazłem, jest ręczne skompilowanie IEnumerablemetody contoller.

string arrayKey = "p[]=";
var pArray = HttpContext.Request.QueryString.Value
    .Split('&')
    .Where(s => s.Contains(arrayKey))
    .Select(s => s.Substring(arrayKey.Length));
x5657
źródło
0

Pracuję z asp.net core 2.2 i jquery i muszę przesłać złożony obiekt („główna klasa”) z widoku do kontrolera z prostymi polami danych i niektórymi tablicami.
Jak tylko dodałem tablicę w definicji `` klasy głównej '' c # (patrz poniżej) i przesłałem (poprawną wypełnioną) tablicę przez ajax (post), cały obiekt był pusty w kontrolerze.
Po pierwsze, pomyślałem, że przyczyną był brak „tradycyjnego: prawda” w moim wywołaniu Ajax, ale tak nie jest.
W moim przypadku powodem była definicja w c # „main class”.
W `` klasie głównej '' miałem:

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

a EreignisTagNeu został zdefiniowany jako:

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

Musiałem zmienić definicję w `` klasie głównej '' na:

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

Teraz działa.
Więc ... dla mnie wydaje się, że rdzeń asp.net ma problem (z postem), jeśli lista dla tablicy nie jest całkowicie zdefiniowana w `` klasie głównej ''.
Uwaga: w moim przypadku działa to z lub bez „tradycyjnego: prawda” w wywołaniu Ajax

FredyWenger
źródło
-3

Musisz przekonwertować tablicę na ciąg:

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

działa to nawet w postaci int, long lub string

public ActionResult MyAction(int[] arrayOfValues )
dr Crow
źródło
Nie jest to nawet poprawna składnia do wysyłania tablicy na serwer. Po prostu przekazujesz obiekt i zakładasz, że jest to tablica, co nigdy nie będzie miało miejsca w przypadku tego, co podałeś, czyli STRING.
Twister1002