发送/ POST操作收集数据从HTML /剃刀形式的MVC操作参数模型 [英] Sending/POSTing collection data from an HTML/Razor form to an MVC action argument model

查看:75
本文介绍了发送/ POST操作收集数据从HTML /剃刀形式的MVC操作参数模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个项目,以帮助学生和顾问选择最好的课程,下学期,使用ASP.NET MVC 5.第一步是为学生选择他已经从列表中所采取的课程。其中显示列表中的控制器是:

I am working on a project to help students and advisers select the best courses for the next semester, using ASP.NET MVC 5. The first step is for the student to select the courses he has already taken from a list. The controller which displays the list is:

public ActionResult AddCourseVM (int? id)
    {
        Student student = db.Students.Find(id);
        // List<BaseCourse> potentialCourses = student.StudentConcentration.RequiredCourses.ToList();
        List<BaseCourse> potentialCourses = db.BaseCourses.ToList();
        AddCourseViewModel vModel = new AddCourseViewModel(student, potentialCourses);

        List<Course> listCourses = new List<Course>();

        foreach(BaseCourse baseC in potentialCourses)
        {
            Course c = new Course();
            c.BaseCourse = baseC;
            c.Student = student;
            listCourses.Add(c);
        }

        vModel.PossibleCourses = listCourses;

        return View("AddCourseVM", vModel);
    }

该视图模型是:

public class AddCourseViewModel
{
    public Student Student { get; set; }
    public List<BaseCourse> AvailCourses { get; set; }
    public List<Course> PossibleCourses { get; set; }

    public AddCourseViewModel(Student s, List<BaseCourse> c)
    {
        Student = s;
        AvailCourses = c;
        PossibleCourses = new List<Course>();
    }

    public AddCourseViewModel()
    {
        Student = new Student();
        AvailCourses = new List<BaseCourse>();
        PossibleCourses = new List<Course>();
    }
}

课程对象是当然的特定实例(对于给定的学生,在一定的学期,等),在路基对象是从课程目录中的个别课程。

The Course objects are specific instances of a course (for a given student, in a certain semester, etc), the BaseCourse objects are the individual courses from the course catalog.

我在列表中使用该视图中显示的可能的课程:

I am displaying the possible courses in a list using this view:

    @model CMPSAdvising.ViewModels.AddCourseViewModel
@{
    ViewBag.Title = "AddCourseVM";
}

<h2>Add Courses</h2>

<div>
    <p>Name: @Model.Student.FirstName @Model.Student.LastName</p>
    <p>W#: @Model.Student.WNumber</p>
</div>

<div>
        <p>Select the Courses You Have Taken</p>
</div>
<div>
    @using (Html.BeginForm("AddCourseVM","Students"))
    {
        @Html.AntiForgeryToken();
        <div>
            <table class="table table-bordered">
                <tr>
                    <th>Course</th>
                    <th>Department</th>
                    <th>Number</th>
                    <th>Check if Taken</th>
                    <th>Semester</th>
                    <th>Grade</th>
                </tr>
                @foreach (var course in Model.PossibleCourses)
                {
                    <tr>
                        <td>@course.BaseCourse.Name</td>
                        <td>@course.BaseCourse.CourseNumber</td>
                        <td>@course.BaseCourse.CourseNumber</td>
                        <td>@Html.CheckBoxFor(s => course.Selected)</td>
                        <td>@Html.TextBoxFor(m => course.Semester)</td>
                        <td>@Html.TextBoxFor(g => course.Grade)</td>
                    </tr>
                }
            </table>
            <input type="submit" value="Save Classes Taken" class="btn btn-default" />
        </div>
    }
</div>

和最后接收的POST当用户点击按钮控制器:

And finally the controller that receives the POST when the user hits the button:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult AddCourseVM (AddCourseViewModel vModel)
    {
        Student stu = vModel.Student;
        foreach (Course c in vModel.PossibleCourses)
        {
            if (c.Selected)
            {
                stu.CoursesTaken.Add(c);
            }
        }

        db.Entry(stu).State = EntityState.Modified;
        db.SaveChanges();

        return RedirectToAction("ListTakenCourses", new { id = stu.ID });
    }

我的问题是,AddCourseViewModel对象(vModel)就要回来了空。我想获得的视图模型从该网页后面为对象,或至少让被检查过的课程列表和学生的ID。

My problem is that the AddCourseViewModel object (vModel) is coming back null. I would like to get the ViewModel back from the web page as an object, or at least get the list of courses that were checked and the student's ID.

推荐答案

我相信有一个应用程序那个叫BeginCollectionItem的HtmlHelper 。这是简要讨论与这里引用,是基于的博客文章几年前由史蒂夫·桑德森书面

I believe there is an app for that called the BeginCollectionItem HtmlHelper. It is discussed briefly with references here, and is based on a blog article written by Steve Sanderson a few years ago.

问题是,模型形式的集合结合是不完全一样的模型与MVC标量输入具有约束力。您的收藏需要一个索引,这里讨论的。如果按预期的不具约束力,检查的是那些获得提供的表单输入名称的属性,并将它们与post模型(动作参数)类中的属性名称和结构。

The problem is that model binding with form collections is not quite the same as model binding with scalar inputs in MVC. Your collection needs an indexer, as discussed here. If it is not binding as expected, examine the name attributes of the form inputs that get rendered, and compare them to the property names and structures within the post model (action argument) class.

从外观上来看,这看起来更像是这个HTML输出应该导致操作参数是不是null:

From the looks of it, HTML output that looked more like this should cause the action argument to be not null:

<tr>
    <td>HTTP 101</td>
    <td>HTP-101</td>
    <td>HTP-101</td>
    <td><input type="checkbox" name="PossibleCourses[0].Selected" /></td>
    <td><input type="text" name="PossibleCourses[0].Semester"></td>
    <td><input type="text" name="PossibleCourses[0].Grade"></td>
</tr>
<tr>
    <td>MVC 101</td>
    <td>MVC-101</td>
    <td>MVC-101</td>
    <td><input type="checkbox" name="PossibleCourses[1].Selected" /></td>
    <td><input type="text" name="PossibleCourses[1].Semester"></td>
    <td><input type="text" name="PossibleCourses[1].Grade"></td>
</tr>

...等,以下哪种剃须刀应该输出:

...and so on, which the following razor should output:

@for (var i = 0; i <= Model.PossibleCourses.Count; i++)
{
    var course = Model.PossibleCourses[i];
    <tr>
        <td>@course.BaseCourse.Name</td>
        <td>@course.BaseCourse.CourseNumber</td>
        <td>@course.BaseCourse.CourseNumber</td>
        <td>@Html.CheckBox(string.Format("PossibleCourses[{0}].Selected", i),
            course.Selected)</td>
        <td>@Html.TextBox(string.Format("PossibleCourses[{0}].Semester", i),
            course.Semester)</td>
        <td>@Html.TextBox(string.Format("PossibleCourses[{0}].Grade", i),
            course.Grade)</td>
    </tr>
}

请注意表单输入元素的名称,属性是如何对应的可转位(列表&LT;课程&GT; )的名称属性的操作参数模型和索引( 裹在里面收集课程)的属性名称。这是为了帮助模型绑定弄清楚如何使用数据填充操作参数类的实例,通过输入名称属性匹配方法参数属性名称的一种方式。

Note how the name attributes of the form input elements correspond to the name of the indexable (List<Course>) property in your action argument Model, and the indexed (Course) property names wrapped inside the collection. This is one way to help the model binder figure out how to populate the action argument class instance with data, by making the input name attributes match the method argument property names.

您也可以使用GUID(或任何为此事字符串)作为一个索引,这是什么BeginItemCollection内部一样。下面也应有助于模型绑定能够填充操作参数,以便它不进来为空的操作方法:

You could also use a GUID (or any string for that matter) to serve as an indexer, which is what BeginItemCollection does internally. The following should also help the model binder be able to populate the action argument so that it does not come in as null to the action method:

@foreach (var course in Model.PossibleCourses)
{
    var indexer = Guid.NewGuid(); // or possibly course.CourseId
    <tr>
        <td>@course.BaseCourse.Name</td>
        <td>@course.BaseCourse.CourseNumber</td>
        <td>@course.BaseCourse.CourseNumber</td>
        <td>@Html.Hidden("PossibleCourses.index", indexer)
            @Html.CheckBox(string.Format("PossibleCourses[{0}].Selected", indexer),
            course.Selected)</td>
        <td>@Html.TextBox(string.Format("PossibleCourses[{0}].Semester", indexer),
            course.Semester)</td>
        <td>@Html.TextBox(string.Format("PossibleCourses[{0}].Grade", indexer),
            course.Grade)</td>
    </tr>
}

所有的事情就是每个组对应于在操作参数类集合项目必须共享相同的索引表格元素,并且索引必须是从对应于不同的集合项目的表单元素的其他群体不同操作参数类。该解决方案的样品可以通过阅读这个问题和它的答案理解。

这篇关于发送/ POST操作收集数据从HTML /剃刀形式的MVC操作参数模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆