MVC如何传递对象的列表,列表项POST操作方法 [英] MVC How to pass a list of objects with List Items POST action method

查看:215
本文介绍了MVC如何传递对象的列表,列表项POST操作方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要发布项目从剃刀视图控制器的列表,但我得到的对象为空的List
我的阶级是结构法

型号:

 列表<题材与GT; modelItem一级学科
{
    INT SUBID {获取;设置;}
    字符串名称{;设置;}
    清单<学生> StudentEntires {获取;设置;}
}类StudentEntires
{
    INT StudId {获取;集;}
    字符串名称{;设置;}
    INT马克{获取;设置;}
}

该模型本身就是一个项目列表,每个项目包含子项目的列表为好。例如型号为主题的列表,每个主题包含学生名单,我要输入标记为每一个学生

我的看法是像

  @model的IList<题材与GT;
@ {
   布局=〜/查看/共享/ _Layout.cshtml
}
@using(Html.BeginForm())
{
   @ Html.ValidationSummary(真)
   如果(Model.Count大于0)
   {
       @for(INT项= 0;项目< Model.Count();项目++)
       {
           < B> @Model [项目] .Name点< / B>< BR />
           @foreach(StudentEntires markItem在型号[项目] .StudentEntires)
           {
               @ Html.TextBoxFor(modelItem => markItem.Mark)
           }
       }
       < p =风格文本对齐:中心>
           <输入类型=提交级=BTN BTN-主要值=更新/>
       &所述; / P>
    }
}

和控制器中

  [HttpPost]
    公众的ActionResult OptionalMarks(INT标识,ICollection的<题材与GT;模型)
    {
        //但我的模型为空。这个任何想法?
    }


解决方案

您会发现这很困难,因为你不使用MVC框架的全部功能,所以让我提供一个工作的例子。

首先亮相,让我们创建一个视图模型来封装视图的数据要求:

 公共类SubjectGradesViewModel
{
    公共SubjectGradesViewModel()
    {
        主题=新的List<个体GT;();
    }    公开名单<个体GT;主题{搞定;组; }
}

接下来,创建一个类来重新present你的主题模式:

 公共类主题
{
    公众诠释标识{搞定;组; }
    公共字符串名称{;组; }
    公开名单<的Student GT; StudentEntries {搞定;组; }
}

最后,一个类来重新present学生:

 公共类学生
{
    公众诠释标识{搞定;组; }
    公共字符串名称{;组; }
    公众诠释级{搞定;组; }
}

在这一点上,你有你需要重新present数据的所有类。现在,让我们创建两个控制器动作,包括一些示例数据,所以你可以看到这是如何工作:

 公众的ActionResult指数()
{
    VAR模型=新SubjectGradesViewModel();    //这个样本数​​据通常会取
    //从数据库
    VAR compsci =新主题
    {
        ID = 1,
        NAME =计算机科学,
        StudentEntries =新的List<的Student GT;()
        {
            新的学生{ID = 1,名称=1 CompSci},
            新的学生{ID = 2,名称=CompSci 2},
        }
    };    VAR数学=新主题
    {
        ID = 2,
        NAME =数学,
        StudentEntries =新的List<的Student GT;()
        {
            新的学生{ID = 3,名称=数学1},
            新的学生{ID = 4,名称=数学2},
        }
    };    model.Subjects.Add(compsci);
    model.Subjects.Add(数学);    返回查看(模型);
}[HttpPost]
公众的ActionResult指数(SubjectGradesViewModel模型)
{
    如果(ModelState.IsValid)
    {
        返回RedirectToAction(成功);
    }    //有验证错误
    //所以重新显示形式
    返回查看(模型);
}

现在是时候建造的意见,当它涉及到将数据发送回控制器,这部分就显得尤为重要。首先登场的是首页查看:

  @model SubjectGradesViewModel@using(Html.BeginForm())
{
    @ Html.ValidationSummary(真)    @ Html.EditorFor(M = GT; m.Subjects)LT; BR />
    <输入类型=提交/>
}

您会注意到我只是使用 Html.EditorFor ,而通过主题作为参数。我这样做的原因是因为我们要创建一个 EditorTemplate 重新present一个主题。我将解释以后多。现在,只知道 EditorTemplates DisplayTemplates 在MVC特殊的文件夹名称,以便它们的名称和位置,都重要的。

我们实际上是要创建两个模板:一个用于主题和一个学生。要做到这一点,请按照下列步骤操作:


  1. 创建视图的当前文件夹内的 EditorTemplates 文件夹(例如,如果你的观点是首页\\ Index.cshtml ,创建该文件夹首页\\ EditorTemplates )。

  2. 创建与名称目录中的一个强类型的视图,你的模型(即匹配在这种情况下你会作出两种观点,这将被称为 Subject.cshtml 分别 Student.cshtml ,(同样的命名很重要))。

Subject.cshtml 应该是这样的:

  @model主题< B> @ Model.Name< / B>< BR />@ Html.HiddenFor(M = GT; m.Id)
@ Html.HiddenFor(M = GT; m.Name)
@ Html.EditorFor(M = GT; m.StudentEntries)

Student.cshtml 应该是这样的:

  @model学生@ Html.HiddenFor(M = GT; m.Id)
@ Html.HiddenFor(M = GT; m.Name)
@ Html.DisplayFor(M = GT; m.Name):@ Html.EditorFor(M = GT; m.Grade)
< BR />

就是这样。如果你现在构建并运行该应用程序,把一个断点上的 POST 指数的动作,你会看到被填充正确的模式。

那么,什么是 EditorTemplates ,和同行, DisplayTemplates ?它们允许您创建可重用的意见的部分,让你组织你的意见多一点。

关于他们的伟大的事情是模板助手,也就是 Html.EditorFor Html.DisplayFor ,是足够聪明,当他们在处理与集合的模板就知道了。这意味着你不再需要遍历所有的物品,每次手动调用模板。您还没有执行任何计数()检查,因为助手将处理所有的您。留给你的观点这是清洁,无逻辑的。

当你想发布馆藏一个控制器动作

EditorTemplates 也会产生相应的名称。这使得模型多结合到列表中,不是生成自己这些名字要简单得多。有次,你仍然不得不做,但是这是不是其中之一。

I want to post a List of items to controller from Razor view , but i am getting a List of objects as null My class structre is

Model:

List<Subjects> modelItem

class Subjects
{
    int SubId{get;set;}
    string Name{get;set;}
    List<Students> StudentEntires{get;set;}
}

class StudentEntires
{
    int StudId{get;set;}
    string Name{get;set;}
    int Mark{get;set;}
}

The model itself is a list of items and every items contain List of child items as well. Example model is a list of Subjects and every subject contains a List of Students, and i want to input mark for every student

My View is like

@model IList<Subjects>  
@{   
   Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm())
{    
   @Html.ValidationSummary(true)
   if (Model.Count > 0)
   {
       @for (int item = 0; item < Model.Count(); item++)
       {
           <b>@Model[item].Name</b><br />
           @foreach (StudentEntires markItem in Model[item].StudentEntires)
           {
               @Html.TextBoxFor(modelItem => markItem.Mark)
           }
       }
       <p style="text-align:center">
           <input type="submit" class="btn btn-primary" value="Update" />
       </p>
    }
}

And in controller

    [HttpPost]
    public ActionResult OptionalMarks(int Id,ICollection<Subjects> model)
    {
        //BUt my model is null. Any idea about this?
    }

解决方案

You're finding this difficult because you're not utilising the full power of the MVC framework, so allow me to provide a working example.

First up, let's create a view model to encapsulate your view's data requirements:

public class SubjectGradesViewModel
{
    public SubjectGradesViewModel()
    {
        Subjects = new List<Subject>();
    }

    public List<Subject> Subjects { get; set; }
}

Next, create a class to represent your subject model:

public class Subject
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Student> StudentEntries { get; set; }
}

Finally, a class to represent a student:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Grade { get; set; }
}

At this point, you have all the classes you need to represent your data. Now let's create two controller actions, including some sample data so you can see how this works:

public ActionResult Index()
{
    var model = new SubjectGradesViewModel();

    // This sample data would normally be fetched
    // from your database
    var compsci = new Subject
    {
        Id = 1,
        Name = "Computer Science",
        StudentEntries = new List<Student>()
        {
            new Student { Id = 1, Name = "CompSci 1" },
            new Student { Id = 2, Name = "CompSci 2" },
        }
    };

    var maths = new Subject
    {
        Id = 2,
        Name = "Mathematics",
        StudentEntries = new List<Student>()
        {
            new Student { Id = 3, Name = "Maths 1" },
            new Student { Id = 4, Name = "Maths 2" },
        }
    };

    model.Subjects.Add(compsci);
    model.Subjects.Add(maths);

    return View(model);
}

[HttpPost]
public ActionResult Index(SubjectGradesViewModel model)
{
    if (ModelState.IsValid)
    {
        return RedirectToAction("Success");
    }

    // There were validation errors
    // so redisplay the form
    return View(model);
}

Now it's time to construct the views, and this part is particularly important when it comes to sending data back to a controller. First up is the Index view:

@model SubjectGradesViewModel

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)

    @Html.EditorFor(m => m.Subjects) <br />
    <input type="submit" />
}

You'll notice I'm simply using Html.EditorFor, whilst passing Subjects as the parameter. The reason I'm doing this is because we're going to create an EditorTemplate to represent a Subject. I'll explain more later on. For now, just know that EditorTemplates and DisplayTemplates are special folder names in MVC, so their names, and locations, are important.

We're actually going to create two templates: one for Subject and one for Student. To do that, follow these steps:

  1. Create an EditorTemplates folder inside your view's current folder (e.g. if your view is Home\Index.cshtml, create the folder Home\EditorTemplates).
  2. Create a strongly-typed view in that directory with the name that matches your model (i.e. in this case you would make two views, which would be called Subject.cshtml and Student.cshtml, respectively (again, the naming is important)).

Subject.cshtml should look like this:

@model Subject

<b>@Model.Name</b><br />

@Html.HiddenFor(m => m.Id)
@Html.HiddenFor(m => m.Name)
@Html.EditorFor(m => m.StudentEntries)

Student.cshtml should look like this:

@model Student

@Html.HiddenFor(m => m.Id)
@Html.HiddenFor(m => m.Name)
@Html.DisplayFor(m => m.Name): @Html.EditorFor(m => m.Grade)
<br />

That's it. If you now build and run this application, putting a breakpoint on the POST index action, you'll see the model is correctly populated.

So, what are EditorTemplates, and their counterparts, DisplayTemplates? They allow you to create reusable portions of views, allowing you to organise your views a little more.

The great thing about them is the templated helpers, that is Html.EditorFor and Html.DisplayFor, are smart enough to know when they're dealing with a template for a collection. That means you no longer have to loop over the items, manually invoking a template each time. You also don't have to perform any null or Count() checking, because the helpers will handle that all for you. You're left with views which are clean and free of logic.

EditorTemplates also generate appropriate names when you want to POST collections to a controller action. That makes model binding to a list much, much simpler than generating those names yourself. There are times where you'd still have to do that, but this is not one of them.

这篇关于MVC如何传递对象的列表,列表项POST操作方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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