Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Posting to a list<modeltype> MVC3

I am trying to get my view to post a List back to the action however it keeps coming in as null.

So my Model has a List of WeightEntry objects.

Exercise Model

public class Exercise
{
    public List<WeightEntry> Entries { get; set; }
    public int ExerciseID { get; set; }
    public int ExerciseName { get; set; }
}

WeightEntry Model

public class WeightEntry
{
    public int ID { get; set; }
    public int Weight { get; set; }
    public int Repetition { get; set; }
}

My View contains the ExerciseName and a forloop of WeightEntry objects

@model Mymvc.ViewModels.Exercise
...
<span>@Model.ExerciseName</span>
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <table class="left weight-record">
        <tr>
            <th>Reps</th>
            <th>Weight</th>
        </tr>
        @foreach (var item in Model.Entries)
        {
            <tr>
                <td>
                    @Html.EditorFor(x => item.Repetition)
                </td>
                <td>
                    @Html.EditorFor(x => item.Weight)
                </td>
            </tr>
        }
    </table>
    <input type="submit" value="Save" /> 
}

The Controller Action (Post) Does nothing at the moment. I am just trying to get the binding working before I add the save code.

[HttpPost]
public ActionResult WeightEntry(Exercise exercise)
{
    try
    {
        //Add code here to save and check isvalid    
        return View(exercise);
    }
    catch
    {
        return View(exercise);
    }
}

I have seen a few little tricks with adding a numerator to the form elements' names used in MVC2 but I was wondering if MVC3 was any different? I was hoping it would all bind nicely with ID's being 0 or null but instead the whole List is null when I inspect it after the form posts. Any help is appreciated. Thanks.

like image 844
Danni Avatar asked Feb 16 '12 05:02

Danni


1 Answers

Replace the following loop:

@foreach (var item in Model.Entries)
{
    <tr>
        <td>
            @Html.EditorFor(x => item.Repetition)
         </td>
         <td>
             @Html.EditorFor(x => item.Weight)
         </td>
     </tr>
}

with:

@for (var i = 0; i < Model.Entries.Count; i++)
{
    <tr>
        <td>
            @Html.EditorFor(x => x.Entries[i].Repetition)
         </td>
         <td>
             @Html.EditorFor(x => x.Entries[i].Weight)
         </td>
     </tr>
}

or even better, use editor templates and replace the loop with:

@Html.EditorFor(x => x.Entries)

and then define a custom editor template that will automatically be rendered for each element of the Entries collection (~/Views/Shared/EditorTemplates/WeightEntry.cshtml):

@model WeightEntry
<tr>
    <td>
        @Html.EditorFor(x => x.Repetition)
     </td>
     <td>
         @Html.EditorFor(x => x.Weight)
     </td>
 </tr>

The the generated input elements will have correct names and you will be able to successfully fetch them back in your POST action.

like image 52
Darin Dimitrov Avatar answered Nov 07 '22 06:11

Darin Dimitrov