c# - 我可以在一个 Controller 中有两个 View 模型吗?

标签 c# asp.net-mvc

我无法理解这是否可能。我有一个存储过程和一个 View 模型类和一个 Controller 。我是否可以添加另一个具有不同存储过程的 View 模型类以使用一个 Controller 并将来自两个存储过程的信息显示到一个 View 中?

这是我当前的模型:

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

最佳答案

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

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

然后是 Action 方法:

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

现在您可以将其包装在 View 模型中:

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

将 View 模型视为一种仅表示要在 View 中显示的一部分数据的方式,仅此而已。上面的所有代码都定义了您希望在该 View 中看到的数据。由于 View 模型上的属性是公共(public)的,因此您可以使用当前使用的任何方法将它们填充到 Controller 的操作中。

第二次更新

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

快速而肮脏的方法

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

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

    return View(model);
}

这是 Index View :

@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)
}

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

第二种方法——使用模板

Controller 中的操作保持不变。然而,我们需要做一些其他的改变。我们正在努力将 Index View 变成这样:

@model PeopleViewModel

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

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

  1. 在 View 的当前文件夹中创建一个 DisplayTemplates 文件夹(例如,如果您的 View 是 Home\Index.cshtml,则创建文件夹 Home\DisplayTemplates).
  2. 在该目录中使用与您的模型匹配的名称创建一个强类型 View (即在这种情况下,您将制作两个 View ,分别称为 Job.cshtmlName。 cshtml,分别)。

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

工作.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)

希望这能让事情变得更清楚一些。

关于c# - 我可以在一个 Controller 中有两个 View 模型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19106093/

相关文章:

.net - 如何使用户从唯一的一台机器(通过获取 CPU 串行)登录到 ASP.NET-MVC Web 应用程序

c#:命名空间优先级/优先级?有2个同名类(class)

c# - 在C#中通过继承向类添加私有(private)方法

c# - WIX调试版本 "insufficient privileges to start service"

c# - 如何在使用 Visual Studio 发布应用程序时自动执行 gulp 任务?

c# - 将控制台输出定向到 Windows 窗体中的文本框的好方法是什么?

c# - 选择列表逻辑应该位于 ASP.NET MVC、 View 、模型或 Controller 中的什么位置?

c# - 如何对使用 ServiceStack 的 JsonServiceClient() 的 ASP.NET MVC 操作进行单元测试?

c# - 多个 DbContext 会产生死锁吗?

asp.net-mvc - 当旧文件仍然存在于目录中时 MVC Bundle {version}