2009-05-20 36 views
8

我有一个ASP.Net MVC应用程序与一个模型是几层深含有一个集合。ASP.Net MVC - 模型与收集不填充回发

我相信创建对象的视图都是正确设置的,但是当我将表单发布到服务器时,它并没有在模型中填充集合。

我有一块数据中的哪一个在类层次结构从而发现:

person.PersonDetails.ContactInformation[0].Data; 

此类结构由LinqToSQL创建,并且是ContactInformation EntitySet<ContactData>类型。为了创建我通过下面的视图:

return View(person); 

和视图内我有一个包含一个文本框相关联于上述字段的名称的形式:

<%= Html.TextBox("person.PersonDetails.ContactInformation[0].Data")%> 

POST方法在我的控制器就如下:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create (Person person) 
{ 
    //Do stuff to validate and add to the database 
} 

正是在这一点上,我担心迷路person.PersonDetails.ContactInformation.Count()== 0。所以ModelBinder已经创建了一个ContactInformation对象,但没有用它应该容纳的对象(即ContactData)填充索引0.

我的问题是两倍: 1.我是否采取了正确的方法..即应该这项工作? 2.关于为什么它可能无法填充ContactInformation对象的任何想法?

非常感谢, 理查德

回答

20

我认为你的模型是默认的模型绑定一起工作太复杂。你可以尝试使用多个参数,并与前缀结合他们:

public ActionResult Create( 
    Person person, 
    [Bind(Prefix="Person.PersonDetails")] 
    PersonDetails details, 
    [Bind(Prefix="Person.PersonDetails.ContactInformation")] 
    ContactInformation[] info) 
{ 
     person.PersonDetails = details; 
     person.PersonDetails.ContactInformation = info; 

     ... 
} 

或者你也可以开发自己的自定义模型粘结剂,将了解如何从表单输入派生复杂的模型。

+1

谢谢,完美的作品。我已经尝试过一个更深层次的例子,它可以很好地工作,但你可能是正确的,它正在复杂性中迷失。为了清晰起见,两条评论: 1.我只需要[Bind(Prefix =“Person.PersonDetails.ContactInformation”)] ContactInformation [] info)和模型对象的相应设置。 2. ContactInformation []需要为EntitySet 以对应正确的类型。 现在查找一些前缀的更多细节.... 感谢您的帮助。 Richard – Richbits 2009-05-20 13:06:01

0

也许缺乏绑定属性是这样的:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create ([Bind] Person person) 
{ 
// Do stuff to validate and add to the database 
} 
+0

谢谢,我给了这个尝试没有运气。它绑定到该人并创建对象到ContactInformation对象的事实表明它是绑定的,而不是ContactData级别。 – Richbits 2009-05-20 12:24:34

+0

不,绑定只在参数上需要,如果您需要更改默认绑定规则。 – 2009-05-20 12:33:36

0

Html.TextBox的第一个参数是文本框的名字,第二个是值。

“错误”:

<%= Html.TextBox("person.PersonDetails.ContactInformation[0].Data")%> 

“右”:

<%= Html.TextBox("nameoftextbox", person.PersonDetails.ContactInformation[0].Data)%> 
+2

谢谢,但我的理解是,第二个参数是用来填充文本框的值。编辑方案。 defaultmodelbinder使用第一个值将表单绑定到回发时创建的对象。 – Richbits 2009-05-20 12:18:58

+0

我的不好........... – Ropstah 2009-05-20 12:27:10

5

如果某个属性为null,则模型联编程序其他人无法找到它,或者无法在提交的表单中找到创建该属性类型实例所需的值。例如,如果属性具有不可空的ID,并且表单不包含该ID的任何数据,则模型联编程序将将该属性留为空,因为它无法在不知道该ID的情况下创建该类型的新实例。

换句话说,要诊断此问题,您必须仔细比较提交表单中的数据(这很容易与Firebug或Fiddler一起查看)与您期望模型绑定器填充的对象的结构进行比较。如果缺少任何必填字段,或者如果以不能将其转换为所需字段类型的方式提交值,则整个对象将保留为空。

1

我一直是这样同类型的情况下挣扎,最终都实现了深层的问题是,MVC默认模型联编似乎没有在EntitySet的<牛逼>领域,只列出<牛逼>下地干活。然而,我找到了一个似乎可以接受的简单解决方法。就我而言,我有一个与联系人(我的Linq-to-Sql EntitySet)具有一对多关系的公司实体。

因为它似乎是,当我在我的代码EntitySet的改变<联系>列出<联系>的MVC默认模型联编开始预期(即使LTS是不是现在)的工作,我想我会提供一个替代,“别名”属性MVC,这是类型列表<联系>,果然,这似乎工作。

在我公司实体类:


// This is what LINQ-to-SQL will use: 
private EntitySet<Contact> _Contacts = new EntitySet<Contact>(); 
[Association(Storage="_Contacts", OtherKey="CompanyID", ThisKey="ID")] 
public EntitySet<Contact> Contacts 
{ 
    get { return _Contacts; } 
    set { _Contacts.Assign(value); } 
} 

// This is what MVC default model binder (and my View) will use: 
public List<Contact> MvcContacts 
{ 
    get { return _Contacts.ToList<Contact>(); } 
    set { _Contacts.AddRange(value); } 
} 

所以现在,在我看来,我有以下几点:

 
<label>First Name* 
    <%= Html.TextBox("Company.MvcContacts[" + i + "].FirstName") %> 
</label> 
<label>Last Name* 
    <%= Html.TextBox("Company.MvcContacts[" + i + "].LastName") %> 
</label> 

看起来像一个魅力的工作!

祝你好运! -Mike

0

确保您的模型(和所有嵌套模型)正在使用属性(getters/setters)而不是字段。显然,默认联编程序需要属性才能正常运行。我有一个非常相似的情况,通过将必要的字段更改为属性来修复。