【问题标题】:Why isn't MVC binding my nested collection?为什么 MVC 不绑定我的嵌套集合?
【发布时间】:2011-04-20 01:59:34
【问题描述】:

如果有几个我试图通过表单编辑的 linqTOsql 对象。

首先,有 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);
    }

视图没有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 中的默认模型绑定器没有正确绑定嵌套集合?

【问题讨论】:

    标签: c# asp.net-mvc linq-to-sql asp.net-mvc-2 forms


    【解决方案1】:

    我建议您使用 POCO 视图模型,而不是那些杂乱的模型类。它们不适应视图并且难以使用。尝试绑定到诸如EntitySet&lt;T&gt; 之类的LINQ 特定集合不是一个好主意。使用编辑器模板实际上可能有效,但即使有效,请记住它应该是一个临时解决方案,直到您引入正确的视图模型。

    在您的主视图中,将循环替换为:

    <%: 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 对象...无论EditorFor&lt;T&gt; 是否有效,我都应该将我的 linqTOsql 对象复制为普通的旧 C# 对象?当然,我是这种数据绑定级别的新手,但实际上拥有相同结构的两个副本似乎是一个非常糟糕的主意。
    • @quakkels,它不是同一个结构。视图模型是适应视图的类。对于单个模型类,您可以拥有不同的多个视图模型类,例如您拥有的 Stream 类。例如,由于字段不同等原因,您可以将一个视图模型用于编辑视图,而将另一个视图模型用于显示视图等。为了简化视图模型和模型类之间的映射,您可以使用AutoMapper。这个想法是永远不要将真实模型传递给视图,而是为这个特定的视图专门定制一个视图模型类。
    • 因为视图模型适应了视图,使用它们会在你的视图中产生非常干净的代码,因为视图模型已经拥有了所有需要的东西,你不必编写丑陋的循环、条件、等在您的标记中导致意大利面条代码。您不必担心在视图模型中复制某些属性,这就是这些类的用途。
    • 再次感谢您提供的信息。周一回来后我会尝试一下。
    • 它仍然无法与 EditorTemplate 一起使用。但是,当我将 linqTOsql 对象转换为 POCO EditModels (ViewModels) 时,它确实有效。我真的有点沮丧,它不适用于 linq 对象。我一直在研究 Steven Sanderson 的书 Pro ASP.NET MVC 2 Framework,他在他的视图中使用了他的 linq 对象,以便将数据库结构和验证规则集中在一个地方。一般来说,它似乎也只是更少的代码。但是,我想底线是我的表单与 POCO 绑定而不与 LINQ 绑定......我只是希望我知道为什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 2015-02-05
    • 2018-12-02
    相关资源
    最近更新 更多