Wits End with IDictionary<T,T> and ModelBinders, ASP.NET MVC 2.0 – Education Career Blog

Okay, I’m not trying to do anything super complex, I have searched, and searched, and roamed every blog and forum I can find. I am about to tear my hair out because no one just outright shows it working.

I want to use an IDictionary in my Model. Nevermind the reason why, that’s irrelevant. I just want to do something very simple, and understand what is going on.

Can someone please help me figure out the HTML I should be putting in the View to make this work right? Please? I have tried Html.TextBoxFor and it comes back null on the postback. I have tried manually using the index of the dictionary item, and it comes back null. I am really getting frustrated, and all I keep seeing is redirection to blogs that don’t answer the question.

Controller

    public ActionResult DictionaryView()
    {
        var model = new Dictionary<string, int>
        {
            { "First", 0 },
            { "Second", 0 },
            { "Third", 0 },
            { "Fourth", 0 }
        };

        return View(model);
    }

    HttpPost
    public ActionResult DictionaryView(Dictionary<string, int> dictionary)
    {
        return null;
    }

HTML

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<System.Collections.Generic.IDictionary<string,int>>" %>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">

    <h2>Dictionary</h2>
<% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>
    <% for (int i = 0; i < Model.Count; i++) { %>
        **// This is there I am stuck!** 
    <% } %>
            <p>
                <input type="submit" value="Submit" />
            </p>
    <% } %>
</asp:Content>

,

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

Example

<%
    int i = 0;
    foreach (KeyValuePair<string, int> pair in Model)
    { %>
    <p>Key: <%= Html.TextBox(String.Format("{0}.key", i), pair.Key)%></p>
    <p>Value: <%= Html.TextBox(String.Format("{0}.value", i), pair.Value)%></p>
<%
    i++;
    }
%>

Edit: This should work

,

Can you use a ViewModel (POCO) instead of a Dictionary? That way your model will have something you can select.

EDIT


ok. So my chops aren’t perfect without intellisense… sorry. But this is my general idea

Public Function DictionaryView() As ActionResult

    Dim model = New System.Collections.Generic.List(Of MyDictionary)
    model.Add(new MyDictionary("First", 0))
    model.Add(new MyDictionary("Second", 0))
    model.Add(new MyDictionary("Third", 0))
    model.Add(new MyDictionary("Forth", 0))

    Return View(model)
End Function


''# This would be your view model.
Public Class MyDictionary
    Public Property TheString
    Public Property TheInt
End Class

Then in your view you can use

model.TheString  
model.TheInt

,

Stacey,

I don’t believe the ModelBinder (the default one anyway), will be able to figure out what you’re trying to do, hence the IDictionary param being null.

Your items will be there in the Request.Params collection. For example:

Request.Params"First"

will return whatever you entered in the first text box. From there, you can pluck them out by hand.

If you want to make this work without using a ViewModel as @rockinthesixstring suggested, you are most likely going to have to write a custom ModelBinder that would do what you want.

If you need an example of this, let me know and I’ll dig up the custom model binder stuff.

BTW, a working view can look like this:

foreach (var pair in Model)
{
    Response.Write(Html.TextBox(pair.Key, pair.Value));
} 

,

You are missing the concept of how to have a separate counter so you have an index and also iterate through the dictionary with a foreach loop:

<% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>
        <% int counter = 0;
           foreach (var kv in Model) { %>
            <input type="text" name="dictionary<%= counter %>.Key" value="<%= kv.Key %>" />
            <input type="text" name="dictionary<%= counter %>.Value" value="<%= kv.Value %>" />
        <%
           counter++;
           } %>
        <p>
            <input type="submit" value="Submit" />
        </p>
<% } %>

Just tested this now, my Controller is a CCP of yours.

And FYI I simply read that blog post to get here. You just had to match your html elements to exactly what Scott posted.

Leave a Comment