Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested binding in ASP.NET MVC Razor

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>

Problem

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.

  • model not binding to dictionary
  • binding dictionary

What am I missing?

like image 407
Max Avatar asked Oct 30 '25 02:10

Max


1 Answers

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>>>>>.

Now to break it down

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.

like image 155
Max Avatar answered Nov 01 '25 16:11

Max



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!