Passing an int array to MVC Controller

10,125

To pass an array of simple values in MVC, you simply need to give the same name to multiple values e.g. The URI will end up looking something like this

/{controllerName}/EditAll?ids=1&ids=2&ids=3&ids=4&ids=5&currentId=1

The default model binding in MVC will bind this to the int array Action parameter correctly.

Now, if it were an array of complex values, there are two approaches that can be taken for model binding. Let's suppose you have a type like so

public class ComplexModel
{
    public string Key { get; set; }

    public string Value { get; set; }
}

and a controller action signature of

public virtual ActionResult EditAll(IEnumerable<ComplexModel> models)
{
}

For model binding correctly, values need to include an indexer in the request e.g.

/{controllerName}/EditAll?models[0].Key=key1&models[0].Value=value1&models[1].Key=key2&models[1].Value=value2

We're using an int indexer here but you can imagine that this might be quite inflexible in an application where items presented to a user in the UI can be added and deleted at any index/slot in the collection. For this purpose, MVC also allows you to specify your own indexer for each item in the collection and pass that value in with the request for the default model binding to use e.g.

/{controllerName}/EditAll?models.Index=myOwnIndex&models[myOwnIndex].Key=key1&models[myOwnIndex].Value=value1&models.Index=anotherIndex&models[anotherIndex].Key=key2&models[anotherIndex].Value=value2

Here we have specified our own indexers, myOwnIndex and anotherIndex for model binding to use to bind a collection of complex types. You can use any string for your indexers as far as I am aware.

Alternatively, you can implement your own model binder to dictate how an incoming request should be bound to a model. This requires more work than using the default framework conventions but does add another layer of flexibility.

Share:
10,125
Scott McKeand
Author by

Scott McKeand

Senior Solutions Developer based in Glasgow

Updated on June 08, 2022

Comments

  • Scott McKeand
    Scott McKeand almost 2 years

    I'm trying to pass an array of int from JavaScript to an MVC controller that accepts 2 parameters - an int array and an int. This is to perform a Page Redirect to the View returned by the Controller Action.

    var dataArray = getAllIds(); //passes back a JavaScript array 
    window.location.replace("/" + controllerName + "/EditAll?ids=" + dataArray + "&currentID=" + dataArray[0])
    

    dataArray contains 1,7 as expected for my sample usage.

    Controller Code

    public virtual ActionResult EditAll(int[] ids, int currentID)
    {
    
      currentModel = GetID(currentID);
      currentVM = Activator.CreateInstance<ViewModel>();
      currentVM.DB = DB;
      currentVM.Model = currentModel;
      currentVM.ViewMode = ViewMode.EditAll;
      currentVM.ModelIDs = ids;
    
      if (currentModel == null)
      {
          return HttpNotFound();
      }
    
      return View("Edit", MasterName, currentVM);
    }
    

    The issue is that when inspecting the int[] ids passed to the controller, it's value is null. currentID is set to 1 as expected.

    I've tried setting jQuery.ajaxSettings.traditional = true which has no effect I've also tried creating a server side url using @Url.Action in JavaScript. I also tried JSON.Stringify before passing the array e.g.

    window.location.replace("/" + controllerName + "/EditAll?ids=" + JSON.stringify(dataArray) + "&currentID=" + dataArray[0])
    

    Again the id array ends up null on the controller side.

    Does anyone have any pointers on getting the int array to pass to the controller correctly? I could declare the parameter as String in the Controller Action and manually serialize and de-serialize the parameter but I need to understand how to get the framework to automatically do simple type conversions.

    Thanks!