I've been stuck a long time to edit a subcollection of my model, the collection of the model was coming null.
I finally found a solution, but I find it a little dirty:
First my tests datas:
Model object:
public class ContainerObject { public String Title { get; set; } public List<ContainedObject> ObjectList { get; set; } }
Sub collection object:
public class ContainedObject { public int Id { get; set; } public String Text { get; set; } public Boolean IsSelected { get; set; } }
Controller method which generate the object
public ActionResult TestForm() { return View(new ContainerObject() { Title = "This is a sample title", ObjectList = new List<ContainedObject>() { new ContainedObject(){Id=1, IsSelected = true, Text="ObjectOne"}, new ContainedObject(){Id=2, IsSelected = false, Text="ObjectTwo"}, new ContainedObject(){Id=3, IsSelected = true, Text="ObjectThree"}, new ContainedObject(){Id=4, IsSelected = false, Text="ObjectFour"}, } }); }
Controller which receive the edited object
[HttpPost] public ActionResult TestFormResult(ContainerObject filledObject) { return View(); }
The view
@model WebTestApplication.Models.ContainerObject @{ ViewBag.Title = "TestForm"; } @using (Html.BeginForm("TestFormResult","Home", FormMethod.Post)){ @Html.EditorFor(x => x.Title) Html.RenderPartial("ContainedObject", Model.ObjectList); <input type="submit" value="Submit"/> }
The partial view(ContainedObject.cshtml)
@model IEnumerable<WebTestApplication.Models.ContainedObject> @{ ViewBag.Title = "ContainedObject"; int i = 0; } @foreach (WebTestApplication.Models.ContainedObject currentObject in Model) { <br /> @Html.Label(currentObject.Text); @Html.CheckBox("ObjectList[" + i + "].IsSelected", currentObject.IsSelected); @Html.Hidden("ObjectList[" + i + "].Id", currentObject.Id); @Html.Hidden("ObjectList[" + i + "].Text", currentObject.Text); i++; }
This is actually working, but I've one problem:
I tried to use Html.EditorFor
instead of Html.RenderPartial
in the view, the problem is that it generate me the name "ObjectList.[0].Id"(with a additional . between the property name and the accessor).
I also tried to use only @Html.EditorFor in the partial view, but it create vars with the name of the object.
If I don't use any template, it works:
@model WebTestApplication.Models.ContainerObject @{ ViewBag.Title = "TestForm"; } @using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post)) { @Html.EditorFor(x => x.Title) for (int i = 0; i < Model.ObjectList.Count; i++) { <br /> @Html.Label(Model.ObjectList[i].Text); @Html.CheckBoxFor(m => Model.ObjectList[i].IsSelected); @Html.HiddenFor(m => Model.ObjectList[i].Id); @Html.HiddenFor(m => Model.ObjectList[i].Text); } <br /><input type="submit" value="Submit"/> }
But here it's a simple template, but in my real case, I will have much more data, and this will be re-used multiple time. So what is my best option?
HtmlHelper - Editor. We have seen different HtmlHelper methods used to generated different html elements in the previous sections. ASP.NET MVC also includes a method that generates html input elements based on the datatype. Editor() or EditorFor() extension method generates html elements based on the data type of the model object's property.
Create HTML Controls for Model Class Properties using EditorFor () ASP.NET MVC includes the method that generates HTML input elements based on the datatype. The Html.Editor () or Html.EditorFor () extension methods generate HTML elements based on the data type of the model object's property.
ASP.NET MVC includes the method that generates HTML input elements based on the datatype. The Html.Editor () or Html.EditorFor () extension methods generate HTML elements based on the data type of the model object's property. The following table list the data types and releted HTML elements:
ASP.NET MVC includes the method that generates HTML input elements based on the datatype. The Html.Editor () or Html.EditorFor () extension methods generate HTML elements based on the data type of the model object's property.
You can simplify your code by introducing the EditorTemplate. Here is how:
TestForm.cshtml
@model WebTestApplication.Models.ContainerObject @{ ViewBag.Title = "TestForm"; Layout = "~/Views/Shared/_Layout.cshtml"; } @using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post)) { @Html.EditorFor(m => m.Title) @Html.EditorFor(m => m.ObjectList); <input type="submit" value="Submit" /> }
ContainedObject.cshtml
@model WebTestApplication.Models.ContainedObject <p> @Html.DisplayFor(m => m.Text) @Html.CheckBoxFor(m => m.IsSelected) @Html.HiddenFor(m => m.Id) @Html.HiddenFor(m => m.Text) </p>
The editor will automatically iterate through the list of objects rendering the view for each of them. Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With