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; }
}
robson
  • 67
  • 2
  • 8

2 Answers2

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)?

Community
  • 1
  • 1
  • Doesn't this create multiple checkboxes with the same ID? This actually seems awkward in MVC. – Jonathan Wood Jan 22 '15 at 03:08
  • 1
    No, If you look at the html generated it will create ``, `` 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 –  Jan 22 '15 at 03:12
  • @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 Jan 23 '15 at 03:14
  • @robson. I suspect that fails if the model has no items. `@DisplayNameFor()` has an overload that accepts `IEnumerable` 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](http://stackoverflow.com/questions/12941465/calling-ienumerable-overload-of-displaynamefor) –  Jan 23 '15 at 03:30
  • @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](http://stackoverflow.com/questions/20807869/displaynamefor-from-listobject-in-model) however I'm using FirstOrDefault() as this seems to be the best approach. Thank you again. – robson Jan 24 '15 at 16:32
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?

ManojAnavatti
  • 604
  • 1
  • 7
  • 18