AnimalTesting
AnimalTesting

Reputation: 127

ASP.NET nested list of models is not binding

I'm trying to post a list of models to the server, using ASP.NET's model binding and manipulating a bunch of values with JavaScript. When I send the values to the server, this is what I get:

model.inventory.processed_items[0].id: GA-6570
model.inventory.processed_items[0].event: 
model.inventory.processed_items[0].subevent: 
model.inventory.processed_items[0].restrict_marking: 
model.inventory.processed_items[0].cecp_string: 
model.inventory.processed_items[0].discrepancies: 
model.inventory.processed_items.Index: 0
model.inventory.processed_items[1].id: GD-1000
model.inventory.processed_items[1].event: 
model.inventory.processed_items[1].subevent: 
model.inventory.processed_items[1].restrict_marking: 
model.inventory.processed_items[1].cecp_string: 
model.inventory.processed_items[1].discrepancies: 
model.inventory.processed_items.Index: 1

These are my model classes that I'm binding to (I've omitted any fields that don't really matter to the question):

public class PackageViewModel
{
    public InventoryViewModel inventory { get; set; }
}

public class InventoryViewModel
{
    public List<ProcessedItemViewModel> processed_items { get; set; }
}

public class ProcessedItemViewModel
{
    public string id { get; set; }
    public int @event { get; set; }
    public string subevent { get; set; }
    public string cecp_string { get; set; }
    public string restrict_marking { get; set; }
    public string discrepancies { get; set; }
    public string highest_classification { get; set; }
    public int occurences_count { get; set; }

    public IEnumerable<ProcessedOccurenceViewModel> occurences { get; set; }
}

public class ProcessedOccurenceViewModel
{
    public string text { get; set; }
    public string security_num { get; set; }
    public Nullable<int> media_count { get; set; }
    public string classification { get; set; }
}

This is my controller:

[HttpGet]
public ActionResult Create()
{
    var inventoryVM = new InventoryViewModel
    {
        processed_items = new List<ProcessedItemViewModel>()
    };

    var packageVM = new PackageViewModel {
        inventory = inventoryVM
    };
    return View(packageVM);
}

[HttpPost]
public ActionResult Create(PackageViewModel packageVM)
{
    if (ModelState.IsValid)
    {
         ...
    }
}

When I check packageVM in debugger, the values are not bound to the view model. However, other values excluding this nested list of models are included in the packageVM model during the POST request. I don't understand why this portion is not binding because I have supplied indices and also passed in an empty list to the view.

Upvotes: 0

Views: 684

Answers (1)

user3559349
user3559349

Reputation:

The property names for the values you are sending do not match the model you are binding to. PackageViewModel does not contain a property named model (it contains one named inventory), so instead of

model.inventory.processed_items[0].id: GA-6570

it needs to be

inventory.processed_items[0].id: GA-6570

An easy way to think about this is to consider how you would access the value of a property of the model in the POST method

public ActionResult Create(PackageViewModel packageVM)
{
    // get the id of the first item in processed_items
    string id = packageVM.inventory.processed_items[0].id

Because the parameter in the method is named packageVM, just drop that prefix, (i.e. becomes inventory.processed_items[0].id), and that is what the name of the data needs to be in order to bind.

As a side note, it you are using the strong typed ***For() methods inside a for loop to generate your form controls based on your model, they will generate the correct name attributes, and you can just use $('form').serialize() to correctly generate the data to be sent via your ajax call.

Upvotes: 1

Related Questions