在MVC4中绑定一个包含列表的字典 [英] Binding a dictionary containing a list in MVC4

查看:142
本文介绍了在MVC4中绑定一个包含列表的字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法发表一个包含Dictionary的表单,其中包含一个int作为键和一个对象列表作为值。



最初这只是一个对象列表,工作正常,类型为:

 列表< MyObject>字段

工作标记为

  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。索引,Model.Position)})

现在的字段ID是

  Fields_ {0} __ {1} __ Property1 

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



然而,在回发我现在得到

  [InvalidCastException:指定的转换无效。] 
System.Web.Mvc.CollectionHelpers.ReplaceDictionaryImpl(IDictionary`2字典,IEnumerable`1 newContents)+131

我猜,MVC足够聪明,这个c omplex对象在视图上但不够聪明,可以在我们发回时将它们收集到viewmodel中。



我发现这个另一个人谁有这里的类似问题,他通过不使用字典来解决它,而是创建一个复杂的对象。我想知道,如果有一个更快的方法,不需要我重写整个系统。



任何想法?






更新



我通过获取源代码DefaultModelBinder并进行调整。
我发现源这里。我没有创建自己的Binder,因为我希望所有的高级功能和验证规则适用于所有其他元素。
一旦我得到了DefaultModelBinder编译和工作,我发现字典无法投射复杂项目的部分,并写了一个解决问题的自定义Dictionary更新方法

解决方案

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

I am having trouble posting a form that contains a Dictionary that contains an int as a key and a list of objects as a value.

Originally this was just a List of Objects and that worked fine and the type was:

List<MyObject> Fields

the working markup was

Fields_{0}__Property1

where {0} is the index of the object. To get it to post back the List of Objects I rendered the object with hidden fields like this:

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

This worked well. Now however, we have a dictionary instead of a list and the list is inside the dictionary.

Now the type is:

Dictionary<int, List<MyObject>>.

I tested the format expected when we render the dictionary using Html.HiddenFor and so I've added hidden fields with the required format which now is:

  @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) })

now the field id is

Fields_{0}__{1}__Property1

where {0} is the key of the dictionary and {1} is the index of the object in the list.

However on postback I now get

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

I am guessing MVC is smart enough to render the fields of this complex object on the view but not smart enough to collect them back into the viewmodel when we post back.

I found this other guy who had a similar problem here and he solved it by not using a dictionary but instead creating a complex object. I'm wondering, however, if there's a quicker way that won't require me to rewrite the entire system.

Any ideas?


Update

I solved it by taking the source code of DefaultModelBinder and adjusting it. I found the source here. I didn't create my own Binder because I want all the advanced functionality and validation rules to apply to all other elements. Once I got the DefaultModelBinder compiling and working I found the part where the dictionary was failing to cast the complex items and wrote a custom Dictionary update method that solved the problem

解决方案

You can always create a custom Model Binder to bind objects from request values exactly as you want. Simply create a class that implements the System.Web.Mvc.IModelBinder interface and implement the BindModel() method.

这篇关于在MVC4中绑定一个包含列表的字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆