我可以在一个控制器中有两个视图模型吗?

Mas*_*yah 7 c# asp.net-mvc

我无法理解这是否可行.我有一个存储过程和一个视图模型类和一个控制器.是否可以使用不同的存储过程添加另一个视图模型类以使用一个控制器并将两个存储过程中的信息显示到一个视图中?

这是我目前的型号:

public class People
{
    public class Jobs
    {
        public int jobID { get; set; }
        public string jobName { get; set; }
    }

    public class Names
    {
        public int userId{get;set}
        public string userName {get; set;}
    }
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*n H 13

是的,这完全有可能.只需创建一个视图模型,其中包含将由存储过程填充的属性,然后将其传递给您的视图:

public class PeopleViewModel
{
    public List<Job> Jobs { get; set; }
    public List<Name> Names { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后是动作方法:

public ActionResult Index()
{
    var model = new PeopleViewModel();
    model.Jobs = // ... fetch from database
    model.Names = // ... fetch from database

    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

每条评论更新

如您所述Jobs并且Names是收藏品,您展示的型号代码无法解决您的问题.听起来这就是你真正想要的:

public class Job // Notice I've removed the pluralisation
{
    public int jobID { get; set; }
    public string jobName { get; set; }
}

public class Name // Notice I've removed the pluralisation
{
    public int userId { get; set; }
    public string userName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,您的People类可以包含以下列表:

public class People
{
    public List<Job> Jobs { get; set; }
    public List<Name> Names { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以将其包装在视图模型中:

public class PeopleViewModel
{
    public People People { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后你会从你的行动中填充它:

public ActionResult Index()
{
    var model = new PeopleViewModel();
    model.People = // ... fetch from database

    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

问题是,如果JobsNames不相关,People首先将它们包装在一个类中是没有意义的.您只需执行以下操作(如上所述):

public class PeopleViewModel
{
    public List<Job> Jobs { get; set; }
    public List<Name> Names { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

将视图模型视为仅表示要在视图中显示的数据片段的方式,仅此而已.上面的所有代码都定义了您希望在该视图中看到的数据.由于视图模型上的属性是公共的,您可以使用当前使用的任何方法在控制器的操作中填充它们.

第二次更新

我认为向您展示一个完整的例子可能会对您的观点如何融合起来提供帮助.首先,我将向您展示在视图模型中访问数据的快速而肮脏的方式,然后我将向您展示如何执行相同操作DisplayTemplates.

快速而肮脏的方法

首先,让我们假设我们有一个Index如下所示的动作:

public ActionResult Index()
{
    var model = new PeopleViewModel();
    model.Jobs = // ... fetch from database
    model.Names = // ... fetch from database

    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

这是Index观点:

@model PeopleViewModel

@foreach (var job in Model.Jobs)
{
    @Html.DisplayFor(m => job.JobId)
    @Html.DisplayFor(m => job.JobName)
}

@foreach (var name in Model.Names)
{
    @Html.DisplayFor(m => name.UserId)
    @Html.DisplayFor(m => name.UserName)
}
Run Code Online (Sandbox Code Playgroud)

注意视图如何期望一个实例,PeopleViewModel它只是循环遍历每个集合中的每个单独项目,打印内容.然而,虽然这对于非常简单的视图来说很好,但是将逻辑与HTML混合成为一个维护问题,需要更复杂的视图和更大的项目.考虑到这一点,我们可以使用它DisplayTemplates.

第二种方法 - 使用模板

控制器中的操作保持不变.但是,我们需要进行一些其他更改.我们正在努力的是将Index观点转变为:

@model PeopleViewModel

@Html.DisplayFor(m => m.Jobs)
@Html.DisplayFor(m => m.Names)
Run Code Online (Sandbox Code Playgroud)

通过Html.DisplayFor这种方式调用,它将尝试找到DisplayTemplate与其传递的数据类型相对应的数据.在这种情况下,帮助程序足够聪明,知道我们正在将集合传递给它,因此它将查找与集合包含的数据类型匹配的模板.这意味着我们需要为类型Job和模板制作模板Name.为此,请按照下列步骤操作:

  1. DisplayTemplates在视图的当前文件夹中创建一个文件夹(例如,如果您的视图是Home\Index.cshtml,则创建该文件夹Home\DisplayTemplates).
  2. 创建与您的模型(即在这种情况下,你会作出两种观点,这将被称为相匹配的名称目录中的强类型的视图Job.cshtml,并Name.cshtml分别).

现在,您可以将所有显示逻辑移动到这两个模板中.所以它们看起来如下:

Job.cshtml

@model Job

@Html.DisplayFor(m => m.JobId)
@Html.DisplayFor(m => m.JobName)
Run Code Online (Sandbox Code Playgroud)

Name.cshtml

@model Name

@Html.DisplayFor(m => m.UserId)
@Html.DisplayFor(m => m.UserName)
Run Code Online (Sandbox Code Playgroud)

希望能稍微清理一下.

  • 你太棒了 - 谢谢你! (2认同)