MVC model not binding to dictionary

2019-02-15 14:07发布

问题:

I am using ASP.Net MVC4 (Razor). I have the following code:

Dictionary<string, OccasionObject> occasionList = new Dictionary<string, OccasionObject>()

The key is a string of the category of the occasion. The occassion object has 3 properties: isAttending(bool), ID(int), and Name(string)

In my cshtml file, I do the following:

@foreach(string s in model.occasionList .Keys)
{
   foreach(var o in model.occasionList .Keys[s])
   {
      @Html.CheckBoxFor(m=>m.occasionList[s].FirstOrDefault(ev=>ev.ID == o.ID).isAttending);
   }
}

This binds perfectly on the load, checking boxes that I have manually checked in SQL. However, when I POST this model back to the server, the occasionList dictionary is null. The model is binding fine because other properties I have in the model are still returned.

Any ideas?

Thanks, Dom

回答1:

The model binder treats the dictionary as a collection, if you imagine the dictionary as an IEnumerable<KeyValuePair<string, IEnumerable<OccasionObject>>> it is easy to understand why it isn't bound.

What @Html.CheckBoxFor(m=>m.occasionList[s].FirstOrDefault(ev=>ev.ID == o.ID).isAttending); is generating is:

<input type="checkbox" name="occasionList[0].Value.isAttending" ../>

so the Key is missing.

Try this:

@Html.Hidden("occasionList.Index", s)
@Html.CheckBoxFor(m=>m.occasionList[s].FirstOrDefault(ev=>ev.ID == o.ID).isAttending);
@Html.HiddenFor(m=>m.occasionList[s].Key)

The first hidden is because you potentially will have your indexes out of order, and explicitly providing an ".Index" is the only way to have the model binder work under those circumstances.

Here's another resource that describes model binding to collections.