MVC3 collection model binding with EditorFor

2019-05-29 04:17发布

问题:

Regarding this post and this other one.

Suppose I have the following:

public class Foo
{
   public string Value1 { get; set; }
   public string Value2 { get; set; }
}

public class BarViewModel
{
   public string Baz { get; set; }
   public IList<Foo> Foos { get; set; }
}

And I have a view that receive a BarViewModel:

@model BarViewModel

@Html.EditorFor(model => model.Baz)

<table>
   @for(int i = 0 ; i < Model.Foos.Count ; i ++)
   {
      string name1 = "Foos[" + i.ToString() + "].Value1";
      string name2 = "Foos[" + i.ToString() + "].Value2";

      <tr>
        <td>
           <input type="text" name="@name1" value="@Model.Foos[i].Value1" />
        </td>
        <td>
           <input type="text" name="@name2" value="@Model.Foos[i].Value2" />
        </td>
      </tr>
   }
</table>

And in my controller I have a POST method that recive the BarViewModel.

Given the inputs names generated for Value1 and Value2 are "Foos[0].Value1" and "Foos[1].Value1" and so on, the collection on the BarViewModel, in the POST method, is automatically filled by the ModelBinder. Awesome.

The problem is, if I do it this way in my view :

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

Then the names generated for the input are like "Foos__0__Value1", and that break the model binding. The Foos property of my BarViewModel, in my POST method, is now null

I am missing something?

Edit


If I use EditorFor on the collection itself:

@EditorFor(model => model.Foos)

The names are generated correctly. But that force me to build a ViewModel in /Views/Share to handle the type Foos, that will generate the row, wich I dont really want to do...

Edit 2


I will clarify my question here, I understand that it's a bit vague.

If I do :

@EditorFor(model => model.Foos)

The names of the inputs will have the form "Foos[0].Value1" and the model binding works just fine on posts.

But if I do :

@for(int i = 0 ; i < Model.Foos.Count ; i ++)
{
    @EditorFor(model => Model.Foos[0].Value1)
}

The names takes the form "Foos__0__Value1" and the model binding does not works. On my post method, model.Foos will be null.

Is there a reason why the second syntax breaks the model binding?

回答1:

I'm not entirely sure just exactly what your question is. However, this is how MVC works. EditorFor uses EditorTemplates, and you define an editor template for your type. It doesn't have to go in Share, it can go in whatever level you're using. For instance, you can have it at /Views/Home/EditorTemplates/Foos.cshtml, so long as you aren't using it anywhere other than your Home controller.