我在发布包含字典的表单时遇到问题,该字典包含一个 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.HiddenFor 渲染字典时,我测试了预期的格式,因此我添加了具有所需格式的隐藏字段,现在是:
@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 足够聪明,可以在视图上渲染这个复杂对象的字段,但不够聪明,无法在我们回发时将它们收集回视图模型。
我在这里找到了另一个有类似问题的人,他通过不使用字典而是创建一个复杂对象来解决它。但是,我想知道是否有更快的方法不需要我重写整个系统。
有任何想法吗?
更新
我通过获取 DefaultModelBinder 的源代码并对其进行调整来解决它。我在这里找到了来源。我没有创建自己的 Binder,因为我希望所有高级功能和验证规则都适用于所有其他元素。一旦我得到 DefaultModelBinder 编译和工作,我发现字典无法转换复杂项目的部分并编写了一个自定义字典更新方法来解决问题