1

I have the following Model

public class FooContainer
{
    public int ID { get; set; }
    public string Name { get; set; }
    public IList<Foo> Foos { get; set; }
}

public class Foo
{
    public string Name {get; set; }
    public string Description {get; set;}
}

Example Controller

public class FooController : Controller
{
    public ActionResult Index(){
        return View(new FooContainer());
    }

    [HttpPost]
    public ActionResult Index(FooContainer model){
        //Do stuff with the model
    }
}

I want to create a view which enables the user to CRUD Foos.

Existing Research

I have read the following:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

along with the following SO articles
MVC4 Allowing Users to Edit List Items
MVC4 bind model to ICollection or List in partial

So i know how to pass an IEnumerable<> back and forth, the problem is that i want to pass some container, with other attributes including an IEnumerable<>

Requirement
I want to be able to bind to this complex model so that it is passed completely and in its entirety to the controller. Assume that the controller does nothing but render the view and receive the FooController model on post. Additionally i would like any relevant articles or references to View syntax required to enable this.

Thanks in advance

Community
  • 1
  • 1
David Colwell
  • 2,450
  • 20
  • 31

1 Answers1

2

This should get you started.

Your Models:

public class FooContainer
{
    public int ID { get; set; }
    public string Name { get; set; }
    public IList<Foo> Foos { get; set; }
}

public class Foo
{
    public string Name {get; set; }
    public string Description {get; set;}
}

Your Controller Actions:

[HttpGet]
public ActionResult Foo()
{
    var model = new FooContainer();
    return View("Foo", model);
}

[HttpPost]
public ActionResult Foo(FooContainer model)
{
    ViewBag.Test = m.Foos[1].Name;
    return View("Foo", model);
}

Your View:

@model DriveAway.Web.Models.FooContainer

@using(Html.BeginForm()) 
{
    <p>@Html.TextBoxFor(m => m.ID)</p>
    <p>@Html.TextBoxFor(m => m.Name)</p>   

    for (int i = 0; i < 5; i++)
    {
        <p>@Html.TextBoxFor(m => m.Foos[i].Name)</p>
        <p>@Html.TextBoxFor(m => m.Foos[i].Description)</p>
    }

    <button type="submit">Submit</button>

}

@ViewBag.Test

What happens here is when you press submit, the iList will be sent to your HttpPost Foo() action and there you can do whatever you want with it. In my example, it'll show whatever was input into the second Name text box. You can obviously loop through each value and check if filled out etc. e.g.

foreach (var f in m.Foos)
   if (!string.IsNullOrEmpty(f.Name) && !string.IsNullOrEmpty(f.Description))
       addToDB(f); // some method to add to to a database

In the view i used a for loop with a limit of 5. But this is obviously up to you.

mnsr
  • 12,337
  • 4
  • 53
  • 79
  • Hi Rudeovski, I am not sure if this is what i am after, i will have a look. I'm not sure how this will pass back the whole container, it looks like it will pass back an IEnumerable to the controller (which i can get working already). I want to pass the complex model, not just a list. – David Colwell Jul 09 '13 at 01:22
  • It'll pass the whole FooContainer back. I've added in the other 2 properties into the View. So on submit, it'll pass in ID and Name from FooContainer, and the list of Foos. – mnsr Jul 09 '13 at 01:27