我在发布一个包含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更新方法来解决这个问题