这个问题的答案是对象是从表单中的 POST 数据重新构成的。这是相当基本的,但 MVC 隐藏了太多正在发生的事情,以至于当您尝试了解 (MVC) 方位时很难看到。
项目的顺序是:
- 创建包含所有必要字段的表单;对未显示的键 (ID) 使用隐藏字段。
- 用户与网页交互;然后按下表单提交按钮。
- 所有字段数据都已发布到控制器页面。
- MVC 将数据重新构成类对象。
- 控制器页面以重构的类实例作为形式参数调用。
注意事项:
创建页面时:生成一个表单,其中包含所表示对象的每个部分的字段。 MVC 对 ID 和其他未显示的数据以及验证规则使用隐藏字段。
值得注意的是,表单是(通常)通过在 _CreateOrEdit.cshtml 页面上列出所有对象属性来创建的:
// Edit.cshtml
@model Person
@Html.Partial("_CreateOrEdit", Model)
和
// _CreateOrEdit.cshtml
@model Person
@Html.HiddenFor(model => model.PersonID)
@Html.LabelFor(model => model.first_name, "First Name")
@Html.EditorFor(model => model.first_name)
@Html.LabelFor(model => model.last_name, "Last Name")
@Html.EditorFor(model => model.last_name)
@Html.LabelFor(model => model.favorite_color, "Favorite Color")
@Html.EditorFor(model => model.favorite_color)
//etcetera
或者使用类的模板(模板必须与它们所代表的类同名,并且它们位于Views\Shared\EditorTemplates 文件夹中)。
使用模板页面与之前的方法几乎相同:
// Edit.cshtml
@model Person
@Html.EditorForModel()
和
// Shared\EditorTemplates\Person.cshtml
@model Person
@Html.HiddenFor(model => model.PersonID)
@Html.LabelFor(model => model.first_name, "First Name")
@Html.EditorFor(model => model.first_name)
@Html.LabelFor(model => model.last_name, "Last Name")
@Html.EditorFor(model => model.last_name)
@Html.LabelFor(model => model.favorite_color, "Favorite Color")
@Html.EditorFor(model => model.favorite_color)
//etcetera
使用模板方法可以很容易地将(对象的)列表添加到表单中。 Person.cshtml 变为:
// Shared\EditorTemplates\Person.cshtml
@model Person
@Html.HiddenFor(model => model.PersonID)
@Html.LabelFor(model => model.first_name, "First Name")
@Html.EditorFor(model => model.first_name)
@Html.LabelFor(model => model.last_name, "Last Name")
@Html.EditorFor(model => model.last_name)
@Html.LabelFor(model => model.favorite_color, "Favorite Color")
@Html.EditorFor(model => model.favorite_color)
@EditorFor( model => model.Addresses )
//etcetera
和
// Shared\EditorTemplates\Address.cshtml
@model Address
@Html.HiddenFor(model => model.AddressID)
@Html.LabelFor(model => model.street, "Street")
@Html.EditorFor(model => model.street)
@Html.LabelFor(model => model.city, "City")
@Html.EditorFor(model => model.city)
//etcetera
MVC 将根据需要为列表中的每个地址创建尽可能多的表单条目。
POST 完全相反;创建模型对象的新实例,调用默认的无参数构造函数,然后 MVC 填充每个字段。通过反转@Html.EditorFor( model.List ) 的序列化过程来填充列表。请务必注意,您必须确保您的类在构造函数中为列表创建有效容器,否则 MVC 的列表重构将失败:
public class Person
{
public List<Address> Addresses;
public Person()
{
// You always need to create this List object
Addresses = new List<Address>();
}
...
}
就是那个封面。幕后发生了很多事情,但都是可以追踪的。
如果您遇到此问题,请注意两点:
- 确保您拥有
@Html.HiddenFor(...),以获取“幸存”返回服务器所需的一切。
- 使用 Fiddler 或 HTTPLiveHeaders(Firefox 插件)检查 POST 数据的内容。这将让您验证哪些数据被发送回以重新构成新的类实例。我偏爱 Fiddler,因为您可以在任何浏览器上使用它(而且它可以很好地显示表单数据)。
最后一点:有一篇关于使用 MVC 从列表中动态添加/删除元素的好文章:http://jarrettmeyer.com/post/2995732471/nested-collection-models-in-asp-net-mvc-3 这是一篇值得阅读的好文章——是的,它确实适用于 MVC3 和 Razor。