代码之家  ›  专栏  ›  技术社区  ›  Nick

在MVC4中绑定包含列表的字典

  •  0
  • Nick  · 技术社区  · 12 年前

    我在发布一个包含Dictionary的表单时遇到了问题,Dictionary包含一个int作为键和一个对象列表作为值。

    最初这只是一个对象列表,效果很好,类型是:

    List<MyObject> Fields
    

    工作标记为

    Fields_{0}__Property1
    

    其中{0}是对象的索引。为了让它发布回“对象列表”,我渲染了带有隐藏字段的对象,如下所示:

      @Html.HiddenFor(m => m.Property1, new { Name = string.Format("Fields[{0}].Property1", Model.Index), @id = string.Format("Fields_{0}__Property1", Model.Index) })
    

    这很有效。然而,现在我们有一个字典而不是列表,并且列表在字典中。

    现在的类型是:

    Dictionary<int, List<MyObject>>.
    

    当我们使用Html.HiddFor呈现字典时,我测试了预期的格式,因此我添加了具有所需格式的隐藏字段,现在是:

      @Html.HiddenFor(m => m.Property1, new { Name = string.Format("Fields[{0}][{1}].Property1", Model.Index, Model.Position), @id = string.Format("Fields_{0}__{1}__Property1", Model.Index, Model.Position) })
    

    现在字段id为

    Fields_{0}__{1}__Property1
    

    其中{0}是字典的键,{1}是列表中对象的索引。

    然而,在回邮时,我现在得到了

     [InvalidCastException: Specified cast is not valid.]
       System.Web.Mvc.CollectionHelpers.ReplaceDictionaryImpl(IDictionary`2 dictionary, IEnumerable`1 newContents) +131
    

    我猜MVC足够聪明,可以在视图上呈现这个复杂对象的字段,但还不够聪明,无法在我们发布时将它们收集回视图模型中。

    我找到了 this other guy 他在这里遇到了类似的问题,他不使用字典而是创建了一个复杂的对象来解决这个问题。然而,我想知道是否有一种更快的方法不需要我重写整个系统。

    有什么想法吗?


    使现代化

    我通过获取DefaultModelBinder的源代码并对其进行调整来解决这个问题。 我找到了消息来源 here 。我没有创建自己的Binder,因为我希望所有高级功能和验证规则都应用于所有其他元素。 当我编译并使用DefaultModelBinder时,我发现了字典无法强制转换复杂项的部分,并编写了一个自定义的dictionary更新方法来解决这个问题

    1 回复  |  直到 9 年前
        1
  •  1
  •   asymptoticFault    12 年前

    您可以随时创建自定义模型绑定器,以便根据需要从请求值绑定对象。只需创建一个实现 System.Web.Mvc.IModelBinder 接口并实现 BindModel() 方法

    推荐文章