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

本文关键字:两个 视图 模型 单个 控制器 我可以 | 更新日期: 2023-09-27 18:33:20

我很难理解这是否可能。我有一个存储过程和一个视图模型类和一个控制器。是否可以添加另一个具有不同存储过程的视图模型类以使用一个控制器并将两个存储过程中的信息显示在一个视图中?

这是我目前的模型:

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

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

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

public class PeopleViewModel
{
    public List<Job> Jobs { get; set; }
    public List<Name> Names { get; set; }
}

然后操作方法:

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

每条评论更新

正如您所说JobsNames是集合,您展示的模型代码无法解决您的问题。听起来这才是你真正想要的:

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

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

public class People
{
    public List<Job> Jobs { get; set; }
    public List<Name> Names { get; set; }
}

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

public class PeopleViewModel
{
    public People People { get; set; }
}

然后,您将从操作中填充它:

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

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

public class PeopleViewModel
{
    public List<Job> Jobs { get; set; }
    public List<Name> Names { get; set; }
}

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

第二次更新

我认为向您展示一个完整的示例可能会有所帮助,说明如何适合您的观点。 首先,我将向您展示访问视图模型中数据的快速而肮脏的方法,然后我将向您展示如何使用DisplayTemplates执行相同的操作。

快速而肮脏的方法

因此,首先,让我们假设我们有一个名为Index的操作,如下所示:

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

以下是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)
}

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

第二种方法 - 使用模板

控制器中的操作保持不变。 但是,我们需要进行一些其他更改。 我们正在努力将Index视图转换为以下内容:

@model PeopleViewModel
@Html.DisplayFor(m => m.Jobs)
@Html.DisplayFor(m => m.Names)

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

  1. 在视图的当前文件夹中创建一个DisplayTemplates文件夹(例如,如果您的视图Home'Index.cshtml,请创建文件夹Home'DisplayTemplates(。
  2. 在该目录中创建一个与您的模型匹配的名称的强类型视图(即,在这种情况下,您将创建两个视图,分别称为 Job.cshtmlName.cshtml (。

现在,您可以将所有显示逻辑移动到这两个模板中。 因此,它们将如下所示:

Job.cshtml

@model Job
@Html.DisplayFor(m => m.JobId)
@Html.DisplayFor(m => m.JobName)

名称.cshtml

@model Name
@Html.DisplayFor(m => m.UserId)
@Html.DisplayFor(m => m.UserName)

希望这能把事情弄清楚一点。