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

时间:2013-10-01 00:30:37

标签: 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;}
    }
}

1 个答案:

答案 0 :(得分:13)

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

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。< / LI>

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

    Job.cshtml

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

    Name.cshtml

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

    希望能稍微清理一下。