【问题标题】:How to pass a model containing an IEnumerable model (complex) into a controller from a view C# MVC3?如何将包含 IEnumerable 模型(复杂)的模型从视图 C# MVC3 传递到控制器中?
【发布时间】:2012-05-29 12:05:54
【问题描述】:

我浏览了本网站上的其他问题和答案,但找不到我需要的答案。

我有一个 StudentRecord 实体:

public class StudentRecord : Persistent {
        public virtual string LastName { get; set; }
        public virtual string FirstName { get; set; }
        public virtual DateTime Dob { get; set; }
        public virtual int StudentRef { get; set; }
        public virtual IEnumerable<StudentAddress> Addresses { get; set; }
        public virtual StudentAddress Address { get; set; }
        public virtual string Notes { get; set; }
    }

如您所见,它包含一个 StudentAddress 实体以及一个 StudentAddress 的 IEnumerable:

public class StudentAddress: Persistent {
        public virtual int StudentRef { get; set; }
        public virtual string Addressee { get; set; }
        public virtual string Property { get; set; }
        public virtual string District { get; set; }
        public virtual string PostalTown { get; set; }
        public virtual string County { get; set; }
        public virtual string Postcode { get; set; }
    }

我正在将学生记录传递给包含在视图模型中的视图:

public class UserViewModel {
        public StudentRecord Student;      
        public ICurrentUserService CurrentUserService;
        public ParentUser ParentUser;        
    }

然后在表单中显示它以便可以对其进行编辑,并提交表单将 StudentRecord 传递回控制器。除了 StudentRecord 中的地址为空外,一切正常。如果添加了新地址,StudentRecord 中的单个 StudentAddress 也可以使用。

是否可以编辑地址并将其发送回控制器,或者我是否需要将它们以单独的形式放在单独的页面上?我可以做到这一点,但更愿意将它们合二为一。

我的问题可能是不可能,或者可能是我将地址放入表单的方式。一个学生可能有多个地址。

这是表格:(为了清楚起见,我删除了一些 html 布局。“添加另一个地址”复选框显示带有 jquery 的新学生地址部分。)

@using (Html.BeginForm()) {
    Personal Details
    Full Name: @Html.TextBoxFor(x => x.Student.FirstName) @Html.TextBoxFor(x => x.Student.LastName)
    DOB: @Html.TextBoxFor(x => x.Student.Dob)

    @if (Model.Student.Addresses.Any()) {
        // Only print addresses if they exist
            int count = 1;
            int element = 0;
                @if (Model.Student.Addresses.Count() > 1) {
                    foreach (var address in Model.Student.Addresses) {
                        Student Address @count
                        Addressee @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).Addressee)
                        Property @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).Property)
                        District @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).District)
                        Postal Town @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).PostalTown)
                        County @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).County)
                        Postcode @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(element).Postcode)
                        count++;
                        element++;
                    } //end foreach
                } else {
                    Student Address
                    Addressee @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).Addressee)
                    Property @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).Property)
                    District @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).District)
                    Postal Town @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).PostalTown)
                    County @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).County)
                    Postcode @Html.TextBoxFor(x => x.Student.Addresses.ElementAt(0).Postcode)
                } @*end if (Model.Student.Addresses.Count() > 1)*@

                Add another address @Html.CheckBox("Add another address", false, new {@id = "newBox"})

                New Student Address
                Addressee @Html.TextBoxFor(x => x.Student.Address.Addressee)
                Property @Html.TextBoxFor(x => x.Student.Address.Property)
                District @Html.TextBoxFor(x => x.Student.Address.District)
                Postal Town @Html.TextBoxFor(x => x.Student.Address.PostalTown)
                County @Html.TextBoxFor(x => x.Student.Address.County)
                Postcode @Html.TextBoxFor(x => x.Student.Address.Postcode)
    } else {
        No address for this student.
    } @*end if (Model.Student.Addresses.Any())*@

    Notes: @Html.TextAreaFor(x => x.Student.Notes, new { @style = "width: 100%;"})

    <input type="submit" value="Send" class="btn btn-primary" style="clear: both;"/>
} @*end of form*@

【问题讨论】:

    标签: c# asp.net-mvc-3 forms model


    【解决方案1】:

    问题是文本输入控件的name 属性不包含正确的值。我邀请您阅读following blog post 以更好地理解默认模型绑定器用于绑定到集合和字典的约定。

    那么我建议你使用编辑器模板而不是在你的视图中编写 foreach 循环:

    @using (Html.BeginForm()) {
        Personal Details
    
        @Html.LabelFor(x => x.Student.FirstName, "Full Name:")
        @Html.EditorFor(x => x.Student.FirstName) 
        @Html.EditorFor(x => x.Student.LastName)
    
        @Html.LabelFor(x => x.Student.Dob, "DOB:")
        @Html.TextBoxFor(x => x.Student.Dob)
    
        @if (Model.Student.Addresses.Any()) {
            @Html.EditorFor(x => x.Student.Addresses)
        } else {
            <text>No address for this student.</text>
        }
    
        @Html.LabelFor(x => x.Student.Notes, "Notes:")
        @Html.TextAreaFor(x => x.Student.Notes, new { @style = "width: 100%;"})
    
        <input type="submit" value="Send" class="btn btn-primary" style="clear: both;"/>
    }
    

    然后定义一个自定义编辑器模板,该模板将为 Addresses 集合的每个元素自动呈现 (~/Views/Shared/EditorTemplates/StudentAddress.cshtml):

    @model StudentAddress
    @Html.LabelFor(x => x.Addressee, "Addressee")
    @Html.EditorFor(x => x.Addressee)
    
    @Html.LabelFor(x => x.Property, "Property")
    @Html.EditorFor(x => x.Property)
    
    @Html.LabelFor(x => x.District, "District")
    @Html.EditorFor(x => x.District)
    
    @Html.LabelFor(x => x.PostalTown, "Postal Town")
    @Html.EditorFor(x => x.PostalTown)
    
    @Html.LabelFor(x => x.County, "County")
    @Html.EditorFor(x => x.County)
    
    @Html.LabelFor(x => x.Postcode, "Postcode")
    @Html.EditorFor(x => x.Postcode)
    

    但这一切都是静态的。如果您希望能够动态添加和删除地址,我邀请您阅读 Steven Sanderson 的 following blog post,其中他说明了如何使用自定义 HTML 帮助程序为输入字段生成正确的名称 (Html.BeginCollectionItem) 和使用 AJAX 添加新行。

    【讨论】:

    • 感谢您的快速回复。我会试一试,看看你建议的阅读材料。我将在这里发布我的结果。非常感谢。
    • 谢谢您,这非常有效。我也会考虑动态添加地址。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    • 2013-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    相关资源
    最近更新 更多