Here's how I would proceed:
public class TaskViewModel { public string Name { get; set; } } public class ProjectViewModel { public string ProjectName { get; set; } public IEnumerable<TaskViewModel> Tasks { get; set; } }
then have a controller:
public class ProjectsController: Controller { public ActionResult Index() { var project = new ProjectViewModel { // Fill the collection with 3 tasks Tasks = Enumerable.Range(1, 3).Select(x => new TaskViewModel()) }; return View(project); } [HttpPost] public ActionResult Index(ProjectViewModel project) { if (!ModelState.IsValid) { // The user didn't fill all required fields => // redisplay the form with validation error messages return View(project); } // TODO: do something with the model // You could use AutoMapper here to map // the view model back to a model which you // would then pass to your repository for persisting or whatever // redirect to some success action return RedirectToAction("Success", "Home"); } }
and then the view (~/Views/Projects/Create.cshtml
):
@model AppName.Models.ProjectViewModel @using (Html.BeginForm()) { <div> @Html.LabelFor(x => x.ProjectName) @Html.EditorFor(x => x.ProjectName) @Html.ValidationMessageFor(x => x.ProjectName) </div> @Html.EditorFor(x => x.Tasks) <input type="submit" value="Create!" /> }
and the corresponding task editor template (~/Views/Projects/EditorTemplates/TaskViewModel.cshtml
):
@model AppName.Models.TaskViewModel <div> @Html.LabelFor(x => x.Name) @Html.EditorFor(x => x.Name) @Html.ValidationMessageFor(x => x.Name) </div>