Passer le tableau à l'action mvc via AJAX

124

J'essaie de passer un tableau (ou IEnumerable) d'entiers de via AJAX à une action MVC et j'ai besoin d'un peu d'aide.

le javascript est

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

et l'action du contrôleur est

public ActionResult MyAction(IEnumerable<int> arrayOfValues )

Au moment où la requête est formatée comme

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

Donc j'y suis presque, si je supprime les crochets, j'obtiens la bonne réponse. Comment dois-je passer ce tableau dans mon get afin que le contrôleur puisse reconnaître ce que c'est?

Merci beaucoup pour votre aide

Dave

Dave
la source

Réponses:

149

Définissez la propriété traditionnelle sur true avant d'effectuer l'appel get. c'est à dire:

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 
Chandu
la source
3
Merci! pourriez-vous s'il vous plaît décrire les différences entre ajax traditionnel et non traditionnel? J'aimerais mieux comprendre ce que je fais avec le reste de mon application.
Tom Beech
5
vous pouvez également ajouter le paramètre traditionnel à un seul appel. Ensuite, cela n'affectera pas le reste
Gluip
1
Cette réponse est correcte, mais si vous préférez définir "traditionnel" pour un seul appel, vérifiez la réponse @RionWilliams. Voter les deux. Merci!
kzfabi
@Tom Beech Depuis jQuery 1.4, la méthode $ .param () sérialise les objets profonds de manière récursive pour accueillir les langages de script et les frameworks modernes tels que PHP et Ruby on Rails. Vous pouvez désactiver cette fonctionnalité globalement en définissant jQuery.ajaxSettings.traditional = true;
Alexey Shevelyov
Aucune de ces réponses n'a fonctionné pour moi (peut-être parce que mon contrôleur était un contrôleur d'API?), Mais j'ai trouvé ma solution dans la réponse SO suivante: stackoverflow.com/a/11100414/1751792
Lopsided
119

J'ai eu des problèmes dans le passé en essayant d'effectuer un POST (je ne sais pas si c'est exactement ce que vous faites, mais je me souviens que lorsque vous passez un tableau, traditional doit être défini sur true .

 var arrayOfValues = new Array();

 //Populate arrayOfValues 
 $.ajax({ 
      type: "POST",
      url: "<%= Url.Action("MyAction","Controller")%>",
      traditional: true,
      data: { 'arrayOfValues': arrayOfValues }              
 });
Rion Williams
la source
4
C'est tellement mieux que de le définir aveuglément globalement dans un fichier web.config, comme certains le suggèrent. L'autre a son propre ensemble de bonnes occasions, mais la vôtre devrait être la solution par défaut.
Panzercrisis
Il s'agit simplement d'envoyer des données en tant que paramètre à ActionResult, invoquera-t-il le code Inside ActionResult? Par exemple, s'il existe du code pour insérer un tableau de valeurs dans la base de données, ce code s'exécutera-t-il?
Saurabh
Cela a résolu exactement ce dont j'avais besoin. Mes tableaux ont continué à revenir comme null dans mon contrôleur jusqu'à ce que je l'ajoute et que je les ai dans mon contrôleur comme: IEnumerable <string> array
SeanMC
52

Une réponse assez tardive, mais différente de celles déjà présentes ici:

Si au lieu de $.ajaxvous souhaitez utiliser des fonctions abrégées $.getou $.post, vous pouvez passer des tableaux de cette façon:


Raccourci 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 sténographique

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
}


Remarques:

  • Le paramètre booléen dans $.paramest pour la traditionalpropriété, qui DOIT être truepour que cela fonctionne .
Accroc
la source
2
Merci pour le conseil sur la propriété traditionnelle. Je ne pouvais pas comprendre pourquoi mon paramètre C # était nul. J'ai trouvé que le type "int []" fonctionnera également dans la méthode C # Action.
Dan Randolph du
9

Vous devriez pouvoir le faire très bien:

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

Alors votre méthode d'action serait comme ceci:

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

Pour vous, il semble que vous ayez juste besoin de stringifier vos valeurs. Le JSONValueProvider dans MVC le reconvertira en un IEnumerable pour vous.

Tejs
la source
Merci pour la réponse, mais je pense qu'il me semble que je dois définir le traditionnel sur vrai. J'ai voté comme je pense que cela fonctionnerait aussi.
Dave
9

La réponse pour utiliser l'option «traditionnelle» est correcte. Je fournis juste quelques informations de fond supplémentaires pour ceux qui souhaitent en savoir plus.

Depuis la documentation jQuery:

Depuis jQuery 1.8, la méthode $ .param () n'utilise plus jQuery.ajaxSettings.traditional comme paramètre par défaut et sera par défaut false.

Vous pouvez également en lire plus ici: http://michaelsync.net/2012/04/05/tips-asp-net-mvc-javascriptserializer-3-questions-and-3-answers et http://haacked.com/archive /2008/10/23/model-binding-to-a-list.aspx

HTH

Tom Gerken
la source
2

SI TOUS LES AUTRES ÉCHOUENT ...

Aucune des autres réponses ici n'a résolu mon problème. J'essayais de faire un appel de méthode GET de JavaScript à un contrôleur d'API Web MVC et d'envoyer un tableau d'entiers en tant que paramètre dans cette demande. J'ai essayé toutes les solutions ici, mais le paramètre de mon contrôleur montait toujours NULL (ou Nothing pour les utilisateurs de VB).

J'ai finalement trouvé ma solution dans un autre article SO , et c'était en fait très simple: il suffit d'ajouter l' [FromUri]annotation avant le paramètre array dans le contrôleur ( j'ai également dû faire l'appel en utilisant le paramètre AJAX "traditionnel" pour éviter les annotations entre crochets ). Voir ci-dessous pour le code réel que j'ai utilisé dans mon application.


Signature du contrôleur:

Signature du contrôleur REMARQUE: l'annotation en C # serait [FromUri]


JavaScript:

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

Chaîne URL réelle:

http://randomhostname/api/InventoryApi/GetBalanceField?productIds=42&inventoryFormId=5493&inventoryBalanceType=Beginning
De guingois
la source
2

Un peu tard ici, mais je pourrais utiliser la solution de SNag plus loin dans $ .ajax (). Voici le code si cela peut aider n'importe qui:

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
la source
1

Si vous migrez vers ASP.NET Core MVC à partir de .Net Framework MVC comme je l'étais, les choses ont légèrement changé. L'appel ajax doit être sur l'objet brut en utilisant stringify donc plutôt que de passer des données de { vals: arrayOfValues }celui - ci devrait être JSON.stringify(arrayOfValues)comme suit:

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

L'autre modification qui a été apportée dans ASP.NET Core consiste à empêcher la falsification des demandes intersites.Ainsi, pour les appels à une action MVC à partir d'une méthode ajax, l' [FromBody]attribut doit être appliqué au paramètre d'action comme suit:

public ActionResult MyAction([FromBody] IEnumerable<int> arrayOfValues )
Michael Armitage
la source
Merci, cela a été incroyablement utile après l'échec de chaque autre permutation des moyens d'envoyer les données!
NibblyPig
0

Si vous utilisez ASP.NET Core MVC et que vous devez gérer les crochets (plutôt que d'utiliser l'option "traditionnelle" de jQuery), la seule option que j'ai trouvée est de créer manuellement IEnumerablela méthode du contrôleur.

string arrayKey = "p[]=";
var pArray = HttpContext.Request.QueryString.Value
    .Split('&')
    .Where(s => s.Contains(arrayKey))
    .Select(s => s.Substring(arrayKey.Length));
x5657
la source
0

Je travaille avec asp.net core 2.2 et jquery et je dois soumettre un objet complexe («classe principale») d'une vue à un contrôleur avec des champs de données simples et quelques tableaux.
Dès que j'ai ajouté le tableau dans la définition de la `` classe principale '' c # (voir ci-dessous) et soumis le tableau (correctement rempli) sur ajax (post), l'objet entier était nul dans le contrôleur.
Tout d'abord, j'ai pensé que le "traditionnel: vrai" manquant à mon appel ajax était la raison, mais ce n'est pas le cas.
Dans mon cas, la raison était la définition dans la «classe principale» c #.
Dans la `` classe principale '', j'avais:

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

et EreignisTagNeu a été défini comme:

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

J'ai dû changer la définition de la `` classe principale '' en:

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

Maintenant ça marche.
Donc ... pour moi, il semble que asp.net core ait un problème (avec post), si la liste d'un tableau n'est pas complètement définie dans la «classe principale».
Remarque: dans mon cas, cela fonctionne avec ou sans "traditional: true", à l'appel ajax

FredyWenger
la source
-3

Vous devez convertir Array en chaîne:

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

cela fonctionne même sous forme d'int, long ou string

public ActionResult MyAction(int[] arrayOfValues )
le Dr Crow
la source
Ce n'est même pas la syntaxe correcte pour envoyer un tableau au serveur. Vous passez simplement un objet et supposez qu'il s'agit d'un tableau, ce qui ne sera jamais le cas avec ce que vous avez fourni, qui est une STRING.
Twister1002