129

I'm trying to pass an array (or IEnumerable) of ints from via AJAX to an MVC action and I need a little help.

the javascript is

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

and the controller action is

public ActionResult MyAction(IEnumerable<int> arrayOfValues )

At the moment the request is formatted as

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

So I'm almost there, if I take the square brackets off I get the correct response. How should I be passing that array into my get so that the controller can recognise what it is?

Many thanks for your help

Dave

tereško
  • 58,060
  • 25
  • 98
  • 150
Dave
  • 2,552
  • 5
  • 25
  • 30

12 Answers12

152

Set the traditional property to true before making the get call. i.e.:

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 
Chandu
  • 81,493
  • 19
  • 133
  • 134
  • 3
    thank you! could you please outline the differences between traditional and non traditional ajax? i'd like to better understand what i'm doing to the rest of my application. – Tom Beech Jan 15 '13 at 16:19
  • 5
    you can also add the traditional setting to a single call. Then it will not affect the rest – Gluip Apr 28 '13 at 10:11
  • 1
    This answer is correct, but if you prefer to set "traditional" for a single call check @RionWilliams answer. Voting up both. Thanks! – kzfabi Jun 13 '13 at 19:02
  • @Tom Beech As of jQuery 1.4, the $.param() method serializes deep objects recursively to accommodate modern scripting languages and frameworks such as PHP and Ruby on Rails. You can disable this functionality globally by setting jQuery.ajaxSettings.traditional = true; – Alexey Shevelyov Nov 04 '15 at 20:48
  • None of these answers worked for me (maybe because my controller was an API controller?), but I found my solution in the following SO answer: http://stackoverflow.com/a/11100414/1751792 – Ross Brasseaux Aug 10 '16 at 23:31
  • I tried this and it does work. Why doesn't deep serializing work though? The array members are just int's. I would think deep serializing them shouldn't have any effect. – Jason Cheng Jan 30 '19 at 22:29
  • 1
    Nevermind. I found out the answer. It doesn't have anything to do with deep serialization. The original way php accepted arrays was like this: "arrayOfValues=1&arrayOfValues=2". The newer way to encode things is like this "arrayOfValues[]=1&arrayOfValues[]=2". The second way is better because it's less ambiguous. Very disappointed .net MVC for not parsing the second way. – Jason Cheng Jan 30 '19 at 23:02
127

I have had issues in the past when attempting to perform a POST (not sure if that is exactly what you are doing, but I recall when passing an array in, traditional must be set to true.

 var arrayOfValues = new Array();

 //Populate arrayOfValues 
 $.ajax({ 
      type: "POST",
      url: "<%= Url.Action("MyAction","Controller")%>",
      traditional: true,
      data: { 'arrayOfValues': arrayOfValues }              
 });
Musa
  • 96,336
  • 17
  • 118
  • 137
Rion Williams
  • 74,820
  • 37
  • 200
  • 327
  • 4
    This is so much better than just blindly setting it globally in a web.config file, like some people suggest. The other has its own set of good occasions, but yours should be the default solution. – Panzercrisis Sep 18 '15 at 15:42
  • This is just sending data as parameter to ActionResult , will it invoke the code Inside ActionResult ? For example if there is some code to insert arrayofvalues into database , will that code run ? – Saurabh Aug 09 '17 at 08:34
  • This solved exactly what I needed. My arrays kept coming back as null in my controller until I added this and got them in my controller like : IEnumerable array – SeanMC Aug 17 '17 at 16:40
56

Quite a late, but different answer to the ones already present here:

If instead of $.ajax you'd like to use shorthand functions $.get or $.post, you can pass arrays this way:


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

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


Notes:

  • The boolean parameter in $.param is for the traditional property, which MUST be true for this to work.
scniro
  • 16,844
  • 8
  • 62
  • 106
SNag
  • 17,681
  • 10
  • 54
  • 69
  • 2
    Thanks for the tip about the traditional property. I could not figure out why my C# param was null. I found that the type "int[]" will also work in C# Action method. – Dan Randolph Jul 11 '14 at 21:04
  • This should be the accepted answer. I wanted to point out though - In the ajax call where he uses "data".... this must match the name of the parameter in your action. I tried at first with "data" and a different name, the endpoint is still reached but the data is null. – BrianLegg Jun 09 '23 at 16:32
  • @BrianLegg Yes it must, because `{ data: array }` is a JS object that gets JSON-stringified, and then destructured back at the .NET end into their respective variables having the same names. So if your C# API method had arguments like `(string name, int age)`, your JS object in `$.param` would have to match it like `{ name: "John", age: 40 }`. – SNag Jun 11 '23 at 18:44
9

The answer to use the 'traditional' option is correct. I'm just providing some more background info for this who wish to learn more.

From the jQuery documentation:

As of jQuery 1.8, the $.param() method no longer uses jQuery.ajaxSettings.traditional as its default setting and will default to false.

You can also read more here: http://michaelsync.net/2012/04/05/tips-asp-net-mvc-javascriptserializer-3-questions-and-3-answers and http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

HTH

Tom Gerken
  • 2,930
  • 3
  • 24
  • 28
9

You should be able to do this just fine:

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

Then your action method would be like so:

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

For you, it looks like you just need to stringify your values. The JSONValueProvider in MVC will convert that back into an IEnumerable for you.

Tejs
  • 40,736
  • 10
  • 68
  • 86
  • Thanks for the answer but I think it looks like I need to set traditional to true. Have upvoted as I think this would work too. – Dave Mar 30 '11 at 17:06
4

A bit late here, but I could use SNag's solution further into $.ajax(). Here is the code if it would help anyone:

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 Kumar
  • 4,363
  • 4
  • 32
  • 55
2

IF ALL ELSE FAILS...

None of the other answers here solved my problem. I was attempting to make a GET method call from JavaScript to an MVC Web API controller, and to send an array of integers as a parameter within that request. I tried all the solutions here, but still the parameter on my controller was coming up NULL (or Nothing for you VB users).

I eventually found my solution in a different SO post, and it was actually really simple: Just add the [FromUri] annotation before the array parameter in the controller (I also had to make the call using the "traditional" AJAX setting to avoid bracket annotations). See below for the actual code I used in my application.


Controller Signature:

Controller Signature NOTE: The annotation in C# would be [FromUri]


JavaScript:

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

Actual URL String:

http://randomhostname/api/InventoryApi/GetBalanceField?productIds=42&inventoryFormId=5493&inventoryBalanceType=Beginning
Community
  • 1
  • 1
Ross Brasseaux
  • 3,879
  • 1
  • 28
  • 48
2

If you are migrating to ASP.NET Core MVC from .Net Framework MVC like I was, things have changed slightly. The ajax call must be on the raw object using stringify so rather than passing data of { vals: arrayOfValues } it should be JSON.stringify(arrayOfValues) as follows:

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

The other change that has been made in ASP.NET Core is to prevent cross-site request forgery so for calls to an MVC action from an ajax method the [FromBody] atribute must be applied to the action parameter as follows:

public ActionResult MyAction([FromBody] IEnumerable<int> arrayOfValues )
Michael Armitage
  • 1,502
  • 19
  • 17
0

If you're using ASP.NET Core MVC and need to handle the square brackets (rather than use the jQuery "traditional" option), the only option I've found is to manually build the IEnumerable in the contoller method.

string arrayKey = "p[]=";
var pArray = HttpContext.Request.QueryString.Value
    .Split('&')
    .Where(s => s.Contains(arrayKey))
    .Select(s => s.Substring(arrayKey.Length));
x5657
  • 1,172
  • 2
  • 13
  • 26
0

I work with asp.net core 2.2 and jquery and have to submit a complex object ('main class') from a view to a controller with simple data fields and some array's.
As soon as I have added the array in the c# 'main class' definition (see below) and submitted the (correct filled) array over ajax (post), the whole object was null in the controller.
First, I thought, the missing "traditional: true," to my ajax call was the reason, but this is not the case.
In my case the reason was the definition in the c# 'main class'.
In the 'main class', I had:

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

and EreignisTagNeu was defined as:

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

I had to change the definition in the 'main class' to:

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

Now it works.
So... for me it seems as asp.net core has a problem (with post), if the list for an array is not defined completely in the 'main class'.
Note: In my case this works with or without "traditional: true," to the ajax call

FredyWenger
  • 2,236
  • 2
  • 32
  • 36
0

If you need to pass more parameters where par1 it's an array, the JSON must contain every parameter, I used this code:

$.ajax({
type: "POST",
url: URL,                    
data: JSON.stringify({ par1: val1, par2: val2 }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {},
error: function (result) {}
});
-4

You need to convert Array to string :

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

this works even in form of int, long or string

public ActionResult MyAction(int[] arrayOfValues )
dr.Crow
  • 1,493
  • 14
  • 17
  • This isn't even correct syntax to send an array to the server. You're just passing an object and assuming it is an array, which will never be the case with what you have provided, which is a STRING. – Twister1002 Apr 23 '17 at 17:44