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

ASP.NET MVC Model Binding IList <gt; Parameter

+3


source to share


3 answers


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!

+1


source


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>
}

      

+1


source


your partial should be:

@model IList<myProject.Models.SomeData>

@for (int i = 0; i < Model.Count(); i++)
{
  <tr>
    <td>
      @Html.EditorFor(model => model[i].Description)
    </td>
  </tr>
}

      

also easier to read if you replace i with the element name

+1


source







All Articles