使用 HTML Helper 通过键绑定到字典的 MVC 模型

MVC Model Binding to Dictionary by Key with HTML Helper

在 MVC(4) 中过滤数据列表时,我将多个过滤器输入绑定到 ViewModel 模型中的字典。

我已经能够通过这样的输入文字声明(.aspx 引擎)来做到这一点:

 <input type="text" name='Model.Filters[matchId].Filter' 
                    value='<%: Model.Filters["matchId"].Filter %>' />

其中 "matchId" 是要过滤的列的名称。 Model.Filter 字典定义为

IDictionary<string,FilterObject>

FilterObject 目前只是:

[Serializable]
public class FilterObject
{
    public FilterObject()
    {
        Filter = "";
    }
    public FilterObject(String value)
    {
        Filter = value;
    }
    //[DefaultValue("")]
    public String Filter { get; set; }
}

所以 - 只要 Model.Filters 字典使用过滤器输入的所有键进行初始化,它就可以工作,否则我们自然会得到一个 "key not found" 运行时异常。

将列名字符串硬编码到控制器中是丑陋的,感觉应该可以使用 @Html.TextBoxFor<>(....) 来避免异常,但我找不到有效的语法(或不只是中断无效的索引对象类型等)例如:

Html.TextBoxFor(m=>m.Filters.FirstOrDefault(k=>k.Key=="matchId").Value.Filter)

生产 HTML 个

  <input id="Value_Filter" name="Value.Filter" type="text" value="" />

这显然没有任何用处

我很确定我只是遗漏了一些东西,但我发现的所有字典绑定示例都依赖于循环并绑定到一个 int 索引,我在这一点上很困惑,没有写一个自定义的助手似乎有点矫枉过正。

非常感谢任何帮助:-)

哈!我停止了与潮流的斗争,并为此写了一个Helper,比我想象的要容易:

public static MvcHtmlString TextBoxForFilterDictionary(this HtmlHelper helper, IDictionary<string, FilterObject> filters, string fieldName, object htmlAttributes = null)
    {
        FilterObject filter;
        if (!filters.TryGetValue(fieldName, out filter))
        {
            filter = new FilterObject();
        }
        string nameAttribute = String.Format("Model.Filters[{0}].Filter", fieldName);
        MvcHtmlString html = helper.TextBox(nameAttribute, filter.Filter, htmlAttributes);
        return html;
    }

并且在 HTML:

  <%: Html.TextBoxForFilterDictionary(Model.Filters, "matchId")%>
  <!-- a bunch of other formatting HTML -->
  <%: Html.TextBoxForFilterDictionary(Model.Filters, "matchName")%>
  <!-- and so on -->

我的通用 ViewModel 现在包含列表排序、分页和过滤所需的一切,不需要过滤器字典初始化,也看不到弱类型对象。

值得付出额外的努力!