2011-05-14 110 views
1

尝试当模型对象在MVC3被实例化理解:当模型对象在MVC3(ASP.NET)创建

我有编辑“人”的示意图。每个人可以有多个地址。我在人员视图中显示网格中的地址。

这显示一个人很好用;我有一个局部视图,它遍历Person.Addresses并构建表格/网格。

创建新人时出现问题:人物对象为空,并且Person.Addresses引用是非法的。我确定我在这里错过了一些相当基础的东西:因为MVC将会(自动奇迹地)在“保存”时创建新的人员实例。如果我尝试创建自己的对象实例,似乎会产生反作用,如果我这样做,我不清楚如何将它连接到表单上的其他条目值。

最后一个并发症:Addresses的列表是可选的;完全不合法的地址。

由于关系数据非常普遍,所以必须有一个更简单的解决方案来处理这个问题。所有澄清赞赏!

+0

因此,你实际上是一个人,你正在创造一个人吗? – 2011-05-14 22:25:21

+0

正确。编辑人员时,模型对象已经存在。创建人员时,模型对象为空。 – 2011-05-15 16:46:14

回答

3

这个问题的答案是,对象是从表单中的POST数据重新构成的。这是相当基本的,但是MVC隐藏了很多事情,当你试图获得你的(MVC)轴承时很难看到。

项目的顺序是:

  1. 了所有必要的字段创建表;对未显示的键(ID)使用隐藏字段。
  2. 用户与网页交互;然后按下表单提交按钮。
  3. 所有字段数据都被发送到控制器页面。
  4. MVC将数据重新组成类对象。
  5. 将控制器页面与重新构造的类实例调用为形式参数。

注:

创建页面时:一个形式与用于对象的每个部分的场产生被表示。 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)的序列化过程来填充列表。

public class Person 
{ 
    public List<Address> Addresses; 

    public Person() 
    { 
     // You always need to create this List object 
     Addresses = new List<Address>(); 
    } 

    ... 
} 

,涵盖的是:需要注意的是,你必须确保你的类创建在构造函数列表中的有效容器否则MVC的名单重新宪法将失败是很重要的。幕后有很多事情要做,但都是可追踪的。

两点很重要,如果你有麻烦与此:

  1. 请确保您有@Html.HiddenFor(...)为需要“生存”之旅回服务器的一切。
  2. 使用Fiddler或HTTPLiveHeaders(Firefox插件)检查POST数据的内容。这将让您验证正在发回的数据以重新构建新的类实例。我偏爱Fiddler,因为你可以在任何浏览器中使用它(并且它特别好地显示表单数据)。

最后一点:有关于动态添加/删除从MVC列表中元素的好文章:http://jarrettmeyer.com/post/2995732471/nested-collection-models-in-asp-net-mvc-3这是一个很好的文章,以合作,通过 - 是的,这确实与MVC3和剃刀工作。

0

我假设的地址是在一个表格中,而不是实际的输入元素,可能只是<td> info </td >? 如果是这样,那么他们将不会被实例化,因为没有数据被发回服务器。 您必须使用回传的元素创建此数据,以便将它们映射(按名称)到其属性。模型联编程序将实例化对象,并在回发时将它们传递给控制器​​,如果它可以找到适当命名的发布表单(或查询字符串)元素。

+0

那么,你会将地址表附加到元素列表中,以便它可以成为POST数据的一部分吗?如果是这样,你会如何做到这一点? – 2011-05-15 16:48:27

+0

@Robert最简单的方法是做一些AJAX事情,就像SO上的评论系统是如何工作的。当您点击添加评论时,评论通过AJAX发布,div更新为新内容。您可以使用强类型的局部视图来完成此操作。 – TheHurt 2011-05-15 17:05:05