刚刚花了两个惊人的令人沮丧的时间格式化一些隐藏的字段以正确绑定到操作方法参数 - 我第二次在上周有这种经验 - 我现在非常好奇为什么MVC架构师选择了他们为对象的列表(和字典)所做的特定绑定约定。
这是我对默认绑定引擎所期望的格式的痛苦理解。在我的示例中,我想绑定到List,其中CustomClass类型公开名为PropertyName的公共属性:
<input type="hidden" name="prefix[idx].PropertyName" value="PropertyName[idx] Value" />
前缀是ViewDataDictionary.TemplateInfo.HtmlPrefix,如果已经定义了。
我发现使用索引信息(即[idx]部分)开始引用某些东西是非常反直觉的。我也觉得令人不安的是,我在这个构造中没有任何地方引用我绑定的action方法参数的名称。这似乎与原始模型属性的情况形成鲜明对比:
<input type="hidden" name="Text" value="something" />
public ActionResult SomeActionMethod( string Text )...
我知道我可以在MVC中滚动自己的模型绑定器。这似乎不是对我的时间有利可图的使用,虽然花费数小时试图拼出隐藏字段的正确格式也不利润:),所以也许我会尝试。我也知道我可以让MVC通过使用@ Html.HiddenFor()创建一个类型模板来完成所有繁重工作,然后通过一个简单的局部视图输出CustomClass实例,该视图具有CustomClass作为模型和单行@Html。 DisplayForModel()。但这似乎也在谷仓周围走了很长一段路。此外,使用@ Html.Hidden帮助程序也有局限性(例如,他们在回发后“帮助”突袭缓存以填充值,因此编写@ Html.Hidden(“fieldname”,value)并不保证值将结束输出 - 您可能会在缓存中获得较旧的值,这是今天另一个长达一小时的烦恼。
但我很好奇为什么选择这种格式。为什么不喜欢C / C ++ / C#/ VB之类的东西:
<input name="prefix.ParameterName.PropertyName[idx]" />
修改
关于我将index参数放在我的示例中的好处。你没错,属性没有编入索引,包含的类是。
但是,这并没有改变基本情况。为什么语法不像:
<input name="prefix.ParameterName[0].PropertyName" />
标准语法忽略带有自定义类型集合的参数名称,并从属性名称“猜测”自定义类型。这很奇怪......所以背后一定有一个故事或选择:)。
答案 0 :(得分:0)
实际上,这很有道理。索引是集合,而不是属性。您没有PropertyName的集合,您有CollectionName []的Collection,其具有PropertyName。
换句话说:
public class Foo { public string Bar { get; set; } }
var foos = List<Foo>();
for (var i = 0; i < foos.Length; i++)
{
var prop = foos[i].Bar; // This is the important bit
}
这正是模型绑定器中发生的事情。
当模型绑定器反序列化post值时,它必须知道要将值插入哪个集合,并且必须知道每个项目的索引。因此,必须知道创建一个Foos集合,x个项目,以及每个Bar所关联的索引。