ASP.Net MVC 2 - ModelBinding和Dictionary <int,int =“”> </int,>

时间:2010-05-25 17:20:58

标签: asp.net-mvc-2 idictionary model-binding

在我的界面中,我有一个文本框列表,如下所示: http://screencast.com/t/YjIxNjUyNmU

文本框的数量未知,因为每个文本框都与模板相关联。 在我的页面中,目标是将一个数字与其中一些模板相关联。

以下是HTML代码示例:

<%  // loop on the templates
    foreach(ITemplate template in templates)
    {
        // get the content from the input dictionary
        int val;
        content.TryGetValue(template.Id, out val);
        // convert it as a string
        string value = ((val > 0) ? val.ToString() : string.Empty);

        // compute the element name/id (for dictionary binding)
        string id = ??????????
        string name = ??????????????
%>
        <label for="<%= name %>"><%= template.Name %></label>
        <input type="text" id="<%= id %>" name="<%= name %>" value="<%= value %>" />
        <br />
<%  }
%>

我期望在我的控制器中获得一个IDictionary,其中第一个int是模板ID,另一个是用户给出的计数。

这就是我想要的:

public ActionResult Save(int? id, Dictionary<int, int> countByTemplate)

我尝试了很多东西,但没有任何效果。我试图阅读消息来源,但这是一个迷宫,我正在试图获取有关模型绑定的信息。

问题:

  • 有关模型绑定如何工作的良好资源吗? 我想要详尽无遗,我已经厌倦了84093043博客,讨论了一个特定的例子。
  • 我如何构建我的HTML,用于获取IDictionary(甚至是控制器操作中的IDictionary?

非常感谢你的帮助

2 个答案:

答案 0 :(得分:1)

有关如何编写输入元素以绑定到数组,字典和其他集合的信息,请访问http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

答案 1 :(得分:1)

好的......感谢Levi我能够找到解决方案。 不是更干净的,但它有效。

HTML应该这样写:

<%
int counter = 0;
// loop on the templates
foreach(ITemplate template in templates)
{
        // get the value as text
        int val;
        content.TryGetValue(template.Id, out val);
        var value = ((val > 0) ? val.ToString() : string.Empty);

        // compute the element name (for dictionary binding)
        string id = "cbts_{0}".FormatMe(template.Id);
        string dictKey = "cbts[{0}].Key".FormatMe(counter);
        string dictValue = "cbts[{0}].Value".FormatMe(counter++);
%>
        <input type="hidden" name="<%= dictKey %>" value="<%= template.Id %>" />
        <input type="text" id="<%= id %>" name="<%= dictValue %>" value="<%= value %>" />
        <label for="<%= id %>"><%= template.Name %></label>
        <br />
<%  }
%>

我必须添加一个隐藏字段来存储值。 我引入了一个'假'计数器,只是为了按照ASP.Net MVC想要的方式遍历字典。 结果我得到了一个填充了我的值的字典,当文本框为空时我得到了'0'。

出现了另一个问题:ModelState被认为无效,因为“需要一个值”。我不希望我的值是必需的,但是看看模型绑定器代码,我没有找到告诉绑定器不需要值的方法。

所以我欺骗了我的控制器中的ModelState,删除了所有错误,如下所示:

public ActionResult Save(int? id, Dictionary<int, int> cbts)
{
    // clear all errors from the modelstate
    foreach(var value in this.ModelState.Values)
        value.Errors.Clear();

嗯...我有效地得到了一个解决方案,但HTML现在有点难看,而且违反直觉(使用索引循环遍历非索引集合?)。 而且每次我都会使用这种绑定来完全正常工作时我需要欺骗。

所以我现在打开一个新帖子,使字典绑定更好。 这是:ASP.Net MVC 2 - better ModelBinding for Dictionary<int, int>

编辑 - 感谢Pavel Chuchuva提供更清洁的解决方案。

在控制器代码中,使用nullable int作为字典的值。 添加更多代码,但更清洁。

public ActionResult Save(int? id, Dictionary<int, int?> cbts)
{
    // this is our final dictionary<int, int>
    Dictionary<int, int> cbtsFinal = new Dictionary<int, int>();
    // loop on the dicitonary with nullable values
    foreach(var key in cbts.Keys)
    {
        // if we have a value
        if(cbts[key].HasValue)
            // then put it in the final dictionary
            cbtsFinal.Add(key, cbts[key].Value);
    }