Description
A nested object needs to be bound to a dropdown, there already is a preselected value for the nested objects. The possible values are of an enum type. The dropdownlist with some other data will be posted back to the controller.
Code - types & classes:
[Serializable]
public enum DummyEnum
{
DummyZero = 0,
DummyOne = 1
}
public class Dummy
{
public Guid Id { get; set; }
public Dictionary<Guid, DummyEnum> DummyEnum { get; set; }
}
public class DummyViewModel
{
public Dictionary<Guid, List<Dummy>> Dummies { get; set; }
}
public class DummyController
{
private void Init(DummyViewModel model)
{
model.EnumList = Enum.GetValues(typeof(DummyEnum))
.Cast<DummyEnum>()
.Select(e => new SelectListItem
{
Value = (e).ToString(),
Text = e.ToString()
});
}
}
HTML:
<td>
@Html.DropDownListFor(
m => m.Dummies[dummiesKey][dummyIndex]
.Enum[Id],
new SelectList(Model.EnumList, "Value", "Text", e.ToString()))
</td>
<select
data-val="true"
data-val-required="The Enum field is required."
id="Dummies_guid__0__Enum_guid_"
name="Dummies[guid][0].Enum[guid]"
style="display: none;"
>
<option value="DummyOne">DummyOne</option>
<option selected="selected" value="DummyZero ">DummyZero</option>
</select>
The problem is that the model doesn't seem to be able to map the payload back to an object or misses the reference to the bound object. Everything is filled in correctly the guid, index and the value of the enum.
Payload:
Dummies[guid][0].Enum[guid]: DummyZero
Dummies[guid][0].Enum[guid]: DummyZero
Attempts
I tried with the following ideas but they weren't successfull for me.
What am I missing?
The problem as stated in the question had to do with mvc converting Dictionary to a List<KeyValuePair<Guid, List>>binding or use JSON.
All that needs to be done is break down the object as mvc would and provide the necessary data. As explained in dicitionary binding.
The object was of type Dictionary<Guid, List<Dummy>>. So the object actually becomes List<KeyValuePair<Guid, List<List<KeyValuePair<Guid, enum>>>>>.
MVC needs the index of the first object that is being used. To get this index we need to covert the dictionary to a list ourself. More specific the values or keys of the dictionarys.
var dummies= Model.Dummies[key];
var dummiesIndex = Model.Dummies.Values.ToList().IndexOf(dummies);
The index needs to be provided along side the post. This can be done by adding it above the dropdown as a hidden field along side the key from the dictionary.
@Html.Hidden("dummies.Index", dummiesIndex)
@Html.Hidden("dummies[" + dummiesIndex + "].Key", key)
Next is the List of objects. Again the index needs to be provided for the binding.
@Html.Hidden("dummies[" + dummiesIndex + "].Value.Index", dummyIndex)
The last step is another dictionary, this is just like the first dictionary
@Html.Hidden("dummies[" + dummiesIndex + "].DummyEnum.Index", dummyEnumIndex)
@Html.Hidden("dummies[" + dummiesIndex + "].DummyEnum.Key", yourKey)
For the value you want to actually post you need to follow the complete path like above.
@Html.DefaultCombo("dummies[" + dummiesIndex + "].DummyEnum[" + dummyEnumIndex+ "]", "Value", "Text", Model.EnumList, enum)
Now MVC can remap your objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With