MVC4 binds model to ICollection or List in partial
Given the model
public class Task
{
public int TaskId { get; set; }
public string Title { get; set; }
public ICollection<SomeData> Information { get; set; }
}
Where
public class SomeData
{
public int SomeDataId { get; set; }
public string Description { get; set; }
}
I have an idea
@model myProject.Models.Task
<div>
@Html.LabelFor(model => model.Title)
</div>
<table>
@Html.Partial("_InformationEdit", Model.Information.ToList(), new ViewDataDictionary(Html.ViewDataContainer.ViewData) {
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Information" }})
</table>
and my partial
@model IList<myProject.Models.SomeData>
@for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
@Html.EditorFor(modelItem => Model[i].Description)
</td>
</tr>
}
However
My Html fields are rendered like
<input class="text-box single-line" id="Information__0__Description" name="Information.[0].Description" type="text">
If names should be Information[0].Description
. It got an extra point there, so it won't revert to the model correctly when posted. How can I fix this?
According to model binding to list I can see what my ID should be, but I just can't figure out the correct syntax.
Also, is there a more elegant way to achieve this IEnumerable
with using @foreach
?
Connected:
ASP.Net MVC4 binds "create view" to the model containing the list
source to share
Changing my partial to
@model IList<myProject.Models.SomeData>
@{
var Information = Model;
}
@for (int i = 0; i < Information.Count(); i++)
{
<tr>
<td>
@Html.EditorFor(modelItem => Information[i].Description)
</td>
</tr>
}
Works, but it seems a little odd!
I am assuming the bound object has the same name as the property to which it should be bound with some magic ... Other suggestions or explanations are appreciated!
source to share
You can use <input...
like this:
Page:
<table>
@Html.Partial("_InformationEdit", Model.Information)
</table>
Partial page:
@for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
<input class="text-box single-line" id="Information[@i]Description" name="Information[@i].Description" type="text" value="@Model[i].Description" />
</td>
</tr>
}
Or, to be able to pass the prefix, as in your example, you can keep the page code the same and change your partial, for example:
Page:
<table>
@Html.Partial("_InformationEdit", Model.Information,
new ViewDataDictionary(Html.ViewDataContainer.ViewData)
{
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Information" }
})
</table>
Partial page:
@for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
@{
string fieldName = string.Format("{0}[{1}].Description", ViewData.TemplateInfo.HtmlFieldPrefix, i);
<input class="text-box single-line" id="@fieldName" name="@fieldName" type="text" value="@Model[i].Description" />
}
</td>
</tr>
}
source to share