130

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

12 Answers 12

153

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

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 
7
  • 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
    Commented Jan 15, 2013 at 16:19
  • 5
    you can also add the traditional setting to a single call. Then it will not affect the rest
    – Gluip
    Commented Apr 28, 2013 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
    Commented Jun 13, 2013 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; Commented Nov 4, 2015 at 20:48
  • 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. Commented Jan 30, 2019 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 }              
 });
3
  • 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. Commented Sep 18, 2015 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
    Commented Aug 9, 2017 at 8: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<string> array
    – SeanMC
    Commented Aug 17, 2017 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.
3
  • 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. Commented Jul 11, 2014 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
    Commented Jun 9, 2023 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
    Commented Jun 11, 2023 at 18:44
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.

1
  • 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
    Commented Mar 30, 2011 at 17:06
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

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
}
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
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 )
1
  • Thank you this was incredibly helpful after every other permutation of ways to send the data failed!
    – NibblyPig
    Commented Aug 16, 2019 at 8:49
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));
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

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 )
1
  • 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. Commented Apr 23, 2017 at 17:44

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.