依靠表单中的name属性将模型发布到MVC控制器是好还是坏?

时间:2014-04-30 19:58:17

标签: asp.net-mvc forms

我有一个包含一些复杂类型的模型,包括嵌套列表。所以我不能简单地使用该模型。

我最初的想法是使用knockoutjs来处理用户交互(添加/删除列表项等),并通过ajax发布knockoutjs视图模型。

但是经过一些谷歌搜索后,我发现我可以在我的表单元素中提供有意义的名称属性,并执行常规表单提交以发布我的表单模型。

<input checked="checked" data-val="true" data-val-required="The Boolean field is required." name="Questions[0].SubQuestions[0].OptionAnswers[0]" type="checkbox" value="true">

当然我还需要一些javascript来进行列表操作和填充。

哪种方法更受欢迎?

编辑:

抱歉索引问题。我知道它应该是顺序的并从0开始。我只是从我生成的html中获取了一个随机元素。索引不是我的问题。我只是想知道哪种方法更受欢迎。

我开始喜欢常规表单提交方式,因为它利用了DataAnnotationsHtml.ValidationSummary的验证功能。 ajax帖子的优点是什么?

2 个答案:

答案 0 :(得分:1)

您非常接近了解asp.net mvc模型绑定器如何开箱即用的概念。

This is the link to an article from where I learnt how to achieve similar requirement.

mvc模型绑定器在属性中读取的方式是查找parameterName[index].PropertyName。索引必须从零开始且不间断。假设,如果您的html如下所示,这是一个列表,例如,它可以是您的问题列表,这是一个复杂的类型:

<input type="text" name="people[0].FirstName" value="George" />
<input type="text" name="people[0].LastName" value="Washington" />
<input type="text" name="people[1].FirstName" value="Abraham" />
<input type="text" name="people[1].LastName" value="Lincoln" />
<input type="text" name="people[3].FirstName" value="Thomas" />
<input type="text" name="people[3].LastName" value="Jefferson" />

当您将上述值提交给asp.net mvc控制器时,上述值变为:

people%5B0%5D.FirstName=George&people%5B0%5D.LastName=Washington&people%5B1%5D.FirstName=Abraham&people%5B1%5D.LastName=Lincoln&people%5B3%5D.FirstName=Thomas&people%5B3%5D.LastName=Jefferson

然后,mvc模型绑定器将上述数据读作:

people[0].FirstName = "George"
people[0].LastName = "Washington"
people[1].FirstName = "Abraham"
people[1].LastName = "Lincoln"
people[3].FirstName = "Thomas"
people[3].LastName = "Jefferson"

所以,你可以看到我们有索引0,1和3的列表项。它已经破了!这导致mvc模型绑定器仅将此数据转换为仅有两个项目的类型人员列表,即索引0和1.它排除3,因为索引2处没有数据。

这个答案包含来自同一篇文章的信息。如果您理解这一点,您将了解名称属性的作用,并且您将理解遵循规则是多么容易,并且mvc binder将理解您发布的所有数据。

如果你想确保mvc binder从发布的数据中构建一个列表,即使缺少任何索引,也可以参考Eric的answer

答案 1 :(得分:0)

尤达的answer非常好。但是,有一种已知的方法可以将回复的非连续索引列表设为Phil Haacked describes in Model Binding To A List (Non-Sequential Indices heading)

<input type="hidden" name="products.Index" value="0" />
<input type="text" name="products[0].Name" value="Beer" />
<input type="text" name="products[0].Price" value="7.32" />

<input type="hidden" name="products.Index" value="1" />
<input type="text" name="products[1].Name" value="Chips" />
<input type="text" name="products[1].Price" value="2.23" />

<input type="hidden" name="products.Index" value="3" />
<input type="text" name="products[3].Name" value="Salsa" />
<input type="text" name="products[3].Price" value="1.23" />