kingrichard2005
kingrichard2005

Reputation: 7269

ASP.Net MVC 3 Dictionary Binding

Hello I have a model object defined in an MVC 3 project that has a Dictionary property as follows:

MyObj.ObjDictionary<string,string>

I have two controller methods, one which handles returning the view and another that handles the POSTed form from the view

public ActionResult Scanner(string val_1, string val_2, string val_3)
{
 //Fetch sessionObj from Model
 MyObj sessionObj = getSessionObj(val_1, val_2, val_3);

 //At this point model.ObjDictionary<string,string> contains data
 return View(sessionObj);
}

[HttpParamAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Scanner(MyObj model)
{
  //At this point model.ObjDictionary<string,string> is null
  //i.e. binding is not being properly achieved

  //Validate POSTed data
}

In the View, I iterate through each key-value pair (kvp). It has to be done this way since the property is dynamic and I have no way of knowing how many dictionary values there will be.

@using (Html.BeginForm("Action", "Home")) 
{
    @foreach (var kvp in Model.ObjDictionary)
    {
            <span>@Html.Label("Scan " + @kvp.Key)</span>
            <span>@Html.TextBox(kvp.Key, "", new { @style = "font-size:Medium;width:400px;" })</span>
    }
   <input type="submit" name="Cancel" value="Cancel" />
   <input type="submit" id="Scanner" name="Scanner" value="Scanner" />
}

The goal is to provide a way for users to input data and have that data bound to the values of the specific key. My problem is that the Model.ObjDictionary is null when it gets POSTed. I'm not sure what I'm doing wrong, I read over this article, but this assumes pre-existing values in a dictionary. Is there a way the ModelBinder can bind the data, entered by a user, to a dictionary value mapped to a specific key?

Upvotes: 2

Views: 2840

Answers (2)

Erik Schierboom
Erik Schierboom

Reputation: 16636

For dictionaries, each entry should have one field for the key and one field for the value.

@using (Html.BeginForm("Action", "Home")) 
{
    var index = 0;
    @foreach (var kvp in Model.ObjDictionary)
    {
        <span>@Html.Hidden("ObjDictionary[" + index + "].Key", kvp.Key)
        <span>@Html.Label("Scan " + @kvp.Key)</span>
        <span>@Html.TextBox("ObjDictionary[" + index + "].Value", kvp.Value, new { @style = "font-size:Medium;width:400px;" })</span>
        index++;
    }
   <input type="submit" name="Cancel" value="Cancel" />
   <input type="submit" id="Scanner" name="Scanner" value="Scanner" />
}

By the way, I have encapsulated this functionality in an HTML helper class. You can find it and a working demonstration here: https://github.com/ErikSchierboom/aspnetmvcdictionaryserialization

Upvotes: 0

Mirko
Mirko

Reputation: 4282

The article you referenced answers your question, you simply need to provide the correct names for your controls, try:


@using (Html.BeginForm("Action", "Home")) {
    var i = 0;
    foreach (var kvp in Model.ObjDictionary)
    {
        @Html.Hidden("ObjDictionary[" + i + "].Key", kvp.Key)@kvp.Key
        <span>@Html.TextBox("ObjDictionary[" + i + "].Value", kvp.Value, new { @style = "font-size:Medium;width:400px;" })</span>
        i++;
        <br />
    }

    <input type="submit" value="Submit" />
}

Upvotes: 3

Related Questions