-1

I have the following form that contains data in a multi-dimensional array that I want to send to my server. The problem is I can't see to pick this data up in my controller.

index.html

<form id="my-form" action="/Home/TestingMethod" method="post">
    <table id="people" class="table table-striped">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Owns Item</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>Danny</td>
                <td class="items">
                    <select name="PersonList[1]Item[]" class="form-control">
                        <option value=""></option>
                        <option value="Keys">Keys</option>
                        <option value="Phone">Phone</option>
                    </select>
                </td>
            </tr>
        </tbody>
    </table>
</form>

MyModel

public class MyModel
{
    public List<int> PersonList { get; set; }
}

HomeController

[HttpPost]
public JsonResult TestingMethod(MyModel model)
{
    List<int> list_of_people = model.PersonList;
    return Json("I am the server, I got your data.");
}

The issue is that list_of_people contains 0 elements.

Form data submitted

PersonList[1]Item[]:Phone

related: how to access Javascript multidimensional array in MVC controller

Community
  • 1
  • 1
Danny Cullen
  • 1,782
  • 5
  • 30
  • 47

1 Answers1

2

The naming convention of your select field is incorrect. In order to match your model structure it should look like this:

<select name="PersonList[0]" class="form-control">
<select name="PersonList[1]" class="form-control">
<select name="PersonList[2]" class="form-control">
...

Because the PersonList property is just an array of integers. Also make sure that you are sending integer values if you want to be able to bind to integers:

<option value="0">Keys</option>
<option value="1">Phone</option>
...

And if you want to allow for empty values make sure that your list is defined as a nullable integers:

public class MyModel
{
    public List<int?> PersonList { get; set; }
}

and now you could do this:

<option value=""></option>
<option value="0">Keys</option>
<option value="1">Phone</option>
...

If on the other hand it was a complex property:

public class MyModel
{
    public List<Person> PersonList { get; set; }
}

where Person is defined like this:

public class Person
{
    public List<Item> Items { get; set; }
}

then you could do this:

<select name="PersonList[0].Items[0].SomeProperty" class="form-control">
<select name="PersonList[0].Items[1].SomeProperty" class="form-control">
<select name="PersonList[1].Items[0].SomeProperty" class="form-control">
...

I would also recommend you going through the following post which explains how the model binder works and what is the naming convention that it expects.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Yes this is exactly what I'm after, it's a custom form I have which doesn't directly/easily map using the standard binder to my model. I will give this a go and see if I can get it working. – Danny Cullen Jan 06 '17 at 10:15
  • I have amended to PersonList but my controller is still not picking it up. model.PersonList.Count = 0 – Danny Cullen Jan 06 '17 at 10:25
  • Since PersonList is an array of integers, make sure that your options are also integers: ``. Another important aspect is that the indexes should start at 0, not 1 as shown in my code: ` – Darin Dimitrov Jan 06 '17 at 10:26
  • Well my integers don't start at 0 because that relates to an ID in my database. Does it have to start at 0 in order for it to work? – Danny Cullen Jan 06 '17 at 10:41
  • I am talking about the indexes, not the values. You could very well have the following: ``. Now the first element of the PersonList collection (at index 0) will have the value of `12345` which could reflect the ID in your database. But the index should **always** start at 0, that's how lists and arrays work in .NET. – Darin Dimitrov Jan 06 '17 at 10:47