views:

745

answers:

3

I have a View with a table representing an employee's timesheet. Days across the top, projects down the side, with each day/project intersection containing two values for regular hours and overtime.

The (simplified) class definitions for the page model are:

public class TimesheetFormModel {
    public List<Project> Projects;
    // other things...
}
public class Project {
    public string Name;
    public List<WorkUnit> WorkUnits;
}
public class WorkUnit {
    public DateTime Date;
    public decimal RegularHours;
    public decimal OvertimeHours;
}

The form elements on the page are named as follows in an attempt to get the DefaultModelBinder to pick up on them.

model.Projects[0].Name // "New Project"
model.Projects[0].WorkUnits[0].Date // "5/23/2009 12:00:00 AM"
model.Projects[0].WorkUnits[0].RegularHours // 0
model.Projects[0].WorkUnits[0].OvertimeHours // 0

model.Projects[0].WorkUnits[1].Date // "5/24/2009 12:00:00 AM"
model.Projects[0].WorkUnits[1].RegularHours // 0
model.Projects[0].WorkUnits[1].OvertimeHours // 0

model.Projects[0].WorkUnits[2].Date // "5/25/2009 12:00:00 AM"
model.Projects[0].WorkUnits[2].RegularHours // 0
model.Projects[0].WorkUnits[2].OvertimeHours // 0

// etc.

When the view is submitted however, the model parameter isn't being completely populated. model.Projects contains projects, but the Project's WorkUnits field is empty. Does the DefaultModelBinder support nested collections like I'm trying to do? If not, what should I do?

+3  A: 

I think these links would be a good start when doing complex model binding:

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

and see the section "Built-in Model Binder support for Complex Types"

here: http://weblogs.asp.net/scottgu/archive/2008/10/16/asp-net-mvc-beta-released.aspx#three

Richard
I've seen those links already (especially ScottH's post), but I still don't know how to get the behavior I need. Useful info for others though.
Brant Bobby
+3  A: 

I eventually figured out why DefaultModelBinder wasn't picking up on the properties of WorkUnit: Because they weren't properties, they were fields. DefaultModelBinder only works with properties. Changing the class definition of WorkUnit and Project to use fields made everything click:

public class Project {
    public IList<WorkUnit> WorkUnits { get; set; }
    public string Name { get; set; }
}

public class WorkUnit {
    public DateTime Date { get; set; }
    public decimal RegularHours { get; set; }
    public decimal OvertimeHours { get; set; }
}

(Note: The source code in the original question had Project.Name defined as a field, in my actual code it was a property. This is why the Projects list was getting populated but WorkUnits wasn't.)

Brant Bobby
A: 

It would be helpful if you could provide a little more information about your solution. Specifically, the a snippet of the view output for the nested list and the controller action code used to process the form posting.

JookyDFW