简体   繁体   English

如何将包含IEnumerable模型(复杂)的模型从视图C#MVC3传递到控制器中?

[英]How to pass a model containing an IEnumerable model (complex) into a controller from a view C# MVC3?

I have had a look through other questions and answers on this site but cannot find the answer I need. 我已经浏览了本网站上的其他问题和答案,但找不到我需要的答案。

I have a StudentRecord entity: 我有一个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; }
    }

As you can see it contains a single StudentAddress entity and also an IEnumerable of StudentAddress: 如您所见,它包含一个StudentAddress实体以及一个IEnumerable的StudentAddress:

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; }
    }

I am passing a student record to a view, contained within a viewmodel: 我将学生记录传递给视图,包含在视图模型中:

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

Then displaying it in a form so it can be edited, and submitting the form passes the StudentRecord back to the controller. 然后在表单中显示它以便可以编辑,并提交表单将StudentRecord传递回控制器。 All works fine except the Addresses within the StudentRecord are null. 除了StudentRecord中的地址为空之外,一切正常。 The single StudentAddress in the StudentRecord is for if a new address is added, and that works fine too. StudentRecord中的单个StudentAddress用于添加新地址,并且也可以正常工作。

Is it possible to edit and send the addresses back to the controller, or do I need to have them in a separate form on a separate page? 是否可以编辑地址并将其发送回控制器,或者我是否需要在单独的页面上以单独的形式将它们放在一起? I can do that but would prefer to have it all in one. 我可以做到这一点,但我更愿意把它全部合二为一。

My problem may be that it is not possible, or it may be the way I am putting the addresses into the form. 我的问题可能是它不可能,或者可能是我将地址放入表单的方式。 A student may have more than one address. 学生可能有多个地址。

Here is the form: (I have stripped out some html layout for clarity. The 'Add another address' tickbox shows the New Student Address section with jquery.) 下面是表格:(为了清楚起见,我删除了一些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*@

The problem is that the name attributes of the text input controls do not contain correct values. 问题是文本输入控件的name属性不包含正确的值。 I invite you to read the following blog post to better understand the convention used by the default model binder to bind to collections and dictionaries. 我邀请您阅读以下博客文章,以更好地理解默认模型绑定器用于绑定到集合和词典的约定。

Then I would recommend you using editor templates instead of writing foreach loops in your views: 然后我建议您使用编辑器模板,而不是在视图中编写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;"/>
}

and then define a custom editor template that will be automatically rendered for each element of the Addresses collection ( ~/Views/Shared/EditorTemplates/StudentAddress.cshtml ): 然后定义一个自定义编辑器模板,该模板将自动为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)

But all this is static. 但这一切都是静态的。 If you want to be able to dynamically add and remove addresses I invite you to read the following blog post from Steven Sanderson in which he illustrates how a custom HTML helper could be used to generate proper names for the input fields ( Html.BeginCollectionItem ) and use AJAX to add new rows. 如果您希望能够动态添加和删除地址,我邀请您阅读Steven Sanderson的以下博客文章 ,其中说明了如何使用自定义HTML帮助程序为输入字段生成专有名称( Html.BeginCollectionItem )和使用AJAX添加新行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM