为什么不是MVC绑定我的嵌套集合?
问题描述:
如果有几个linqTOsql对象,我试图通过窗体进行编辑。为什么不是MVC绑定我的嵌套集合?
首先,有个Stream
类:
[Table]
public class Stream
{
[HiddenInput(DisplayValue = false)]
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public long StreamID { get; set; }
/*other properties removes for brevity*/
// relationship (one stream to many Stream2FieldTypes)
// uses EntitySet<Stream2FieldTypes> and OtherKey for the FK in Stream2FieldTypes
private EntitySet<Stream2FieldTypes> _Stream2FieldTypes;
[System.Data.Linq.Mapping.Association(Storage = "_Stream2FieldTypes", OtherKey = "StreamID")]
public EntitySet<Stream2FieldTypes> Stream2FieldTypes
{
get { return this._Stream2FieldTypes; }
set { this._Stream2FieldTypes.Assign(value); }
}
}
然后有Stream2FieldTypes
类:
[Table]
public class Stream2FieldTypes
{
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public long s2fID { get; set; }
/*other properties removed for brevity*/
[Column]
public long StreamID { get; set; } // FK
// relationship (one Stream2FieldTypes to Streams)
private EntitySet<Stream> _Stream;
[Association(Storage = "_Stream", ThisKey = "StreamID")]
public EntitySet<Stream> Stream
{
get { return this._Stream; }
set { this._Stream.Assign(value); }
}
}
我用linqTOsql库来获得这些对象,并将它们发送到这样的观点:
public ActionResult StreamEdit(long id)
{
Genesis.Domain.Entities.Stream stream = genesisRepository.Streams.FirstOrDefault(x => x.StreamID == id);
return View(stream);
}
所有东西都发送到视图没有问题...但是当视图上的表单被提交时,Stream.Stream2FieldTypes
由于某种原因而丢失。我赶上表单提交这个动作:
[HttpPost]
public ActionResult StreamEdit(long id, Genesis.Domain.Entities.Stream form)
{
return View(form);
}
和View是没有Stream2FieldTypes
集合。
的观点写Stream2FieldTypes这样的:
<% for (int i = 0; i < (Model.Stream2FieldTypes != null ? Model.Stream2FieldTypes.Count() : 0); i++) %>
<% { %>
<div class="ListItem">
Label: <%: Html.EditorFor(x => x.Stream2FieldTypes[i].s2fLabel, new { style="width:100px" })%>
Required: <%: Html.EditorFor(x => x.Stream2FieldTypes[i].s2fIsRequired)%>
Field Type ID": <%: Html.EditorFor(x => x.Stream2FieldTypes[i].FieldTypeID, new { style="width:20px;" })%>
Stream ID: <%: Html.EditorFor(x => x.Stream2FieldTypes[i].StreamID) %>
</div>
<% } %>
为什么没有在MVC默认模型绑定正确地结合嵌套集合?
答
我会建议你使用POCO视图模型而不是那些混乱的模型类。他们不适应观点,很难与之合作。试图绑定到LINQ特定的集合,如EntitySet<T>
不是一个好主意。这种使用编辑模板的方式实际上可能会起作用,但即使这种方法奏效,在介绍适当的视图模型之前也应该考虑它是一种临时解决方案。
在你的主观点与此更换循环:
<%: Html.EditorFor(x => x.Stream2FieldTypes) %>
,然后添加一个强类型的~/Views/Home/EditorTemplates/Stream2FieldTypes.ascx
局部视图:
<%@ Control
Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<SomeNs.Stream2FieldTypes>"
%>
<div class="ListItem">
Label:
<%: Html.EditorFor(x => x.s2fLabel, new { style="width:100px" }) %>
Required:
<%: Html.EditorFor(x => x.s2fIsRequired) %>
Field Type ID:
<%: Html.EditorFor(x => x.FieldTypeID, new { style="width:20px;" })%>
Stream ID:
<%: Html.EditorFor(x => x.StreamID) %>
</div>
正常情况下应该采取产生正确的输入名称的照顾,但是为了避免人们以此为例,我再次重复使用适当的视图模型。
感谢您的提示。我没有考虑使用编辑模板。对于POCO对象...无论编辑器是否适用于,我都应该将我的linqTOsql对象复制为普通旧C#对象?当然,我对这个级别的数据绑定是新手,但基本上有两个相同结构的副本似乎是一个非常糟糕的主意。 –
quakkels
2010-10-01 22:01:36
@quakkels,它是不一样的结构。视图模型是适应视图的类。对于单个模型类,您可以拥有不同的多视图模型类,例如“Stream”类。例如,您可以为编辑视图创建一个视图模型,并为显示视图创建另一个视图模型,因为不同的字段等。为了简化视图模型和模型类之间的映射,您可以使用[AutoMapper](http:// automapper)。 codeplex.com/)。这个想法是永远不会将真实模型传递给视图,而是为此特定视图提供专门定制的视图模型类。 – 2010-10-01 22:04:43
由于视图模型适合视图使用它们会导致视图中非常干净的代码,因为视图模型已经拥有了所需的所有内容,并且您不必在标记中编写丑陋的循环,条件等以意大利面代码。你不应该担心重复视图模型中的一些属性,这就是这些类的意图。 – 2010-10-01 22:06:12