0

I am binding objects in a razor foreach in the index.html:

VIEW

@using (Ajax.BeginForm("Save", "Unit", new AjaxOptions { OnSuccess = "onSuccess" }))
    {

<button type="submit" class="btn btn-default" id="saveUnits"><i class="fa fa-save"></i></button>


    <table>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>

                    @Html.HiddenFor(modelItem => item.UnitId)
                    <td>
                        @Html.EditorFor(modelItem => item.Name)
                    </td>
                    <td>
                        @Html.EditorFor(modelItem => item.ErrorText)
                    </td>

                </tr>
            }
        </tbody>
    </table>
}

I have grabbed the data sent to my action parameter with fiddler and got this:

item.UnitId=5&
item.Name=111111111111&
item.ErrorText=fsdddddddddddddddd+&

item.UnitId=5&
item.Name=+&
item.ErrorText=dddddd+&

ACTION

public ActionResult Save(List<Unit> units )
{
    return new EmptyResult();   
}

VIEWMODEL

public class Unit
{
    [HiddenInput(DisplayValue = false)]
    public int UnitId { get; set; }

    [DataType(DataType.MultilineText)]
    public string Name { get; set; }

    [DataType(DataType.MultilineText)]
    public string ErrorText { get; set; 
}

Why is my units instance null? The properties match so they should be bound!

Did I overlook something?

Charles
  • 50,943
  • 13
  • 104
  • 142
Elisabeth
  • 20,496
  • 52
  • 200
  • 321
  • possible duplicate of [MVC 3 - Model Binding a list in a table with each record being a column instead of row](http://stackoverflow.com/questions/10885679/mvc-3-model-binding-a-list-in-a-table-with-each-record-being-a-column-instead) – glautrou Apr 04 '14 at 15:18

1 Answers1

2

You need to use a for loop not a foreach loop. Also, it would be better to make your Model class have a property which is a collection.

Your model could be something like:

public class UnitsViewModel
{
    public List<Unit> Units { get; set; }

    public class Unit
    {
        [HiddenInput(DisplayValue = false)]
        public int UnitId { get; set; }

        [DataType(DataType.MultilineText)]
        public string Name { get; set; }

        [DataType(DataType.MultilineText)]
        public string ErrorText { get; set; }
    }
}

And you could do the following in your cshtml:

@for (int i = 0; i < Model.Count; i++)
{
    <tr>

        @Html.HiddenFor(m => m.Units[i].UnitId)
        <td>
            @Html.EditorFor(m => m.Units[i].Name)
        </td>
        <td>
            @Html.EditorFor(m => m.Units[i].ErrorText)
        </td>

    </tr>
}
Matthew Dresser
  • 11,273
  • 11
  • 76
  • 120
  • but why do the razor scaffold tools make it a foreach ? – Elisabeth Apr 04 '14 at 15:13
  • Get the current element from modelItem[i] and not from Model[i]? That does not make sense. I get an error that I have to use a List because IEnumerable does not know the [] operator. Razor forces me to use Lists??? When I change to a List at the index top site then all my header declations are invalid: @Html.EditorFor(item => item.Name) – Elisabeth Apr 04 '14 at 15:31
  • 1
    http://stackoverflow.com/questions/14165632/asp-net-mvc-4-for-loop-posts-model-collection-properties-but-foreach-does-not OK its a technical limitation it must be a for loop with index else it can not bind the correct item... – Elisabeth Apr 04 '14 at 15:40
  • Had a similar problem the foreach is the culprit. – Yini Jun 06 '14 at 09:18