2

I'm having a frustrating issue where I can't seem to get the Model binding to work with CheckBoxFor when posting back to the controller. My model just returns back null. Any help would be appreciated!

View

@model IEnumerable<FFR.Context.Matchup>

@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>View1</title>
</head>
<body>
<p>
    @Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm(Html.BeginForm("Submit", "Matchups", FormMethod.Post)))
{
    @foreach (var item in Model) {
    <tr>
        <td>@Html.CheckBoxFor(modelItem => item.isChecked)</td>

        <td>
            @Html.DisplayFor(modelItem => item.MatchupDate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Spread)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.HomeScore)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.AwayScore)
        </td>
    }

    <tr><td><input type="submit" value="Submit" /></td></tr>

</table>
}
</body>
</html>

Controller

[HttpPost]
public ActionResult Submit(IEnumerable<Matchup> model)
{

        //processing

}

Model

public partial class Matchup
{
    public Matchup()
    {
        this.Bets = new HashSet<Bet>();
    }

    public int MatchupId { get; set; }
    public int HomeTeamId { get; set; }
    public int AwayTeamId { get; set; }
    public int LocationId { get; set; }
    public System.DateTime MatchupDate { get; set; }
    public int WeekId { get; set; }
    public int SeasonId { get; set; }
    public Nullable<decimal> Spread { get; set; }
    public Nullable<decimal> HomeScore { get; set; }
    public Nullable<decimal> AwayScore { get; set; }
    public string TimeLeft { get; set; }
    public Nullable<System.DateTime> LastUpdate { get; set; }
    public Boolean isChecked { get; set; }
}

2 Answers 2

4

You need to use a for loop so that your controls are correctly names with indexers. Change the model to @model IList<FFR.Context.Matchup> and then in the view

for(int i = 0; i < Model.Count; i++)
{
  @Html.CheckBoxFor(m => m[i].isChecked)
  ....
}

If you cannot use IList then you can use a custom EditorTemplate for your model (refer this example)

Side note: Why would you use Layout = null; and render the head in the view (as opposed to specifying a layout)?

Sign up to request clarification or add additional context in comments.

5 Comments

Doesn't this create multiple checkboxes with the same ID? This actually seems awkward in MVC.
No, If you look at the html generated it will create <input type="checkbox" id="_0__isChecked" name="[0].isChecked" ...>, <input type="checkbox" id="_1__isChecked" name="[1].isChecked" ...> In fact its OP's original code that is creating duplicate id attributes (and name attributes which is why it wouldn't bind to a collection on post back). And I don't see how a for loop is any more awkward that a foreach loop
@StephenMuecke Thank you, this worked perfectly. For others, please note this also required me to change the view slightly for table headers since I had to change to IList. @Html.DisplayNameFor(model => model.MatchupDate) becomes @Html.DisplayNameFor(model=> model[0].MatchupDate)
@robson. I suspect that fails if the model has no items. @DisplayNameFor() has an overload that accepts IEnumerable<T> so you can use @DisplayNameFor(m=> m.MatchupDate) (although intellisense complains until you build). And if your model has a property that is IEnumerable, you can use @Html.DisplayNameFor(m => m.MyCollection.FirstOrDefault().Name) or the answers suggested here
@StephenMuecke Couldn't use m => m.MatchupDate because I'm using IList instead of IEnmerable now. But FirstOrDefault() worked perfectly for me. I will say though that model=> model[0].MatchupDate did work even with no items as referenced here however I'm using FirstOrDefault() as this seems to be the best approach. Thank you again.
0

Hope this link will give you an insight on how the model binding works with the list. http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

Please note you are doing too many things in the view. Try to use editor templates for the simpler views.

Also i notice 2 calls for Begin form. Do you really intend to use like that?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.