当我将模型发送到控制器进行保存时,控制器会获得一个空字典。
出了什么问题?绑定工作有什么特别之处吗?
我的模特有这个属性:
public Dictionary<int, bool> DictionaryTest { get; set; }
我的控制器在调用视图之前填充一些数据:
mymodel.DictionaryTest = new Dictionary<int, bool> { { 0, false }, { 1, true }, { 2, false } };
我的观点使用以下代码正确显示:
@Html.CheckBoxFor(m_ => m_.DictionaryTest[0], new { @class = "form-control" })
@Html.CheckBoxFor(m_ => m_.DictionaryTest[1], new { @class = "form-control" })
@Html.CheckBoxFor(m_ => m_.DictionaryTest[2], new { @class = "form-control" })
非常感谢
答案 0 :(得分:1)
要绑定字典,您需要具有以下内容的值:DictionaryProperty[N].Key
和DictionaryProperty[N].Value
。因此,您的Razor代码需要看起来像:
@Html.HiddenFor(m_ => m_.DictionaryTest[0].Key)
@Html.CheckBoxFor(m_ => m_.DictionaryTest[0].Value, new { @class = "form-control" })
@Html.HiddenFor(m_ => m_.DictionaryTest[1].Key)
@Html.CheckBoxFor(m_ => m_.DictionaryTest[1].Value, new { @class = "form-control" })
@Html.HiddenFor(m_ => m_.DictionaryTest[2].Key)
@Html.CheckBoxFor(m_ => m_.DictionaryTest[2].Value, new { @class = "form-control" })
但是,如果您的键是整数,则字典过度。只需使用一个简单的列表。然后,您的Razor代码将按原样运行。
答案 1 :(得分:1)
我以为我在这里写点什么,因为我尝试了接受的答案并最终得到了汇编问题 - 而且我不了解你们,但是DictionaryTest[index].Key
行只是没有& #39;为我工作 - 因为数组访问何时需要Key
属性?!
对于其他寻求答案的人来说,有一些技巧可以使这一切都像魔法一样。简而言之,这一切都取决于此:
为了将多个属性绑定到一个对象(可以是任何复杂类型的列表或字典),模型绑定器需要知道属于哪些属性 - 否则它纠缠不清。
让我们说你有这样的类型:
public class TestClass
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
你希望它绑定到这样的方法:
public ActionResult MyAction(List<TestClass> test)
{
...
}
如果您只是在页面上转储一堆输入:
<input name="Prop1" value="FirstP1" />
<input name="Prop2" value="FirstP2" />
<input name="Prop1" value="SecondP1" />
<input name="Prop2" value="SecondP2" />
模型装订器如何知道哪些装在一起?简短的回答:它没有 - 它需要一些帮助。您可能已经知道,关键是给它相关的索引,以便它可以找出要分组的那些:
<input name="test[0].Prop1" value="FirstP1" />
<input name="test[0].Prop2" value="FirstP2" />
<input name="test[1].Prop1" value="SecondP1" />
<input name="test[1].Prop2" value="SecondP2" />
现在模型绑定器可以将前两个[0]
组合在一起,将接下来的两个[1]
组合在一起,并且我们有一个列表绑定。
注意:那里的退伍军人会记得,你的指数保持秩序很重要 - 如果他们最终不完整或无序(例如你最终得到{{1} },[0]
,[3]
由于某些客户端删除或排序)然后您将面临麻烦,因为模型绑定器按顺序查看。您可以通过添加一些客户端JS来解决这个问题,以便在表单保存时按顺序重新分配名称 - 这样可以解决问题。或者你可以继续阅读:
一旦你理解了上述内容,让字典绑定实际上非常简单:假设它们只是[1]
:
List<KeyValuePair<X,Y>>
但是,如果您提交的是无序索引,则同样的问题/限制也适用。这里的一个具体方案是复选框 - 如果您要将<input name="test[0].Key" value="Item1" />
<input name="test[0].Value" value="Item1Value" />
<input name="test[1].Key" value="Item2" />
<input name="test[1].Value" value="Item2Value" />
(或任何其他键类型)绑定为复选框,则您会回想起HTML没有&#39;在表单提交中提交未选中的复选框。因此,如果您只勾选一些项目,最终会得到一个部分列表,其中保证索引不合规定。
解决方案1:在表单提交之前,让JS客户端重写索引,强制它们是顺序的。完全可行,但很烦人。
解决方案2:使用无序键,帮助模型绑定器了解要查找的键。这很简单:你只需要一个额外的输入来定义索引:
Dictionary<string, bool>
名为<input type="hidden" name="test.Index" value="IndexA" />
<input name="test[IndexA].Key" value="IndexAKey" />
<input name="test[IndexA].Value" value="IndexAValue" />
<input type="hidden" name="test.Index" value="SomeOtherIndex" />
<input name="test[SomeOtherIndex].Key" value="SomeOtherIndexKey" />
<input name="test[SomeOtherIndex].Value" value="SomeOtherIndexValue" />
的额外输入为模型绑定器提供了将其全部排序所需的轻推。对于字典,使用字典键作为自定义索引很方便,所以一切都排好了 - 感觉有点多余,但确实有效:
<collectionName>.Index
要成为全圆,<input type="hidden" name="test.Index" value="IndexAKey" />
<input name="test[IndexAKey].Key" value="IndexAKey" /> //<-- totally feel like this line doesn't need to be there, but it works
<input name="test[IndexAKey].Value" value="IndexAValue" />
的符号完全是需要发生的 - 但应该是Dictionary[index].Key
,并且在HTML输入string
属性中 - 而不是name
帮助者。
和平外出的人们!