【问题标题】:ASP.NET MVC Pass Multiple Models to View From ControllerASP.NET MVC 将多个模型传递给从控制器查看
【发布时间】:2015-06-30 14:47:46
【问题描述】:

我需要一个视图来显示员工名字和姓氏以及与员工相关的主管名字和姓氏。

我有 2 个模型,它们如下:

public class Employee
{
    public int EmployeeID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Department { get; set; }
    public int SupervisorID { get; set; }

    public virtual ICollection<Supervisor> Supervisor { get; set; }
}

public class Supervisor
{
    public int SupervisorID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public string Department { get; set; }

    public virtual Employee Employee { get; set; }
}

为了显示所需的数据,我创建了另一个模型:

public class EmployeeSupervisor
{
    public int EmployeeID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Department { get; set; }

    public string SupFirstName { get; set; }
    public string SupLastName { get; set; }
    public string SupPhone { get; set; }
    public string SuoEmail { get; set; }
    public string SupDepartment { get; set; }
}

在控制器的详细信息操作中,我执行以下操作:

Employee employee = db.Employees.Find(id);
Supervisor supervisor = db.Supervisors.Find(employee.SupervisorID);

EmployeeSupervisor es = new EmployeeSupervisor
{
    EmployeeID = employee.EmployeeID,
    Department = employee.Department,
    FirstName = employee.FirstName,
    LastName = employee.LastName,
    SupFirstName = supervisor.FirstName,
    SupLastName = supervisor.LastName,
    SuoEmail = supervisor.Email,
    SupPhone = supervisor.Phone,
    SupDepartment = supervisor.Department
};

return View(es);

然后在我的视图中

@model TimeOffV3.Models.EmployeeSupervisor

最后我在视图中执行以下操作

@Html.DisplayFor(model => model.FirstName)
@Html.DisplayFor(model => model.LastName)
@Html.DisplayFor(model => model.SupFirstName)
@Html.DisplayFor(model => model.SupLastName)

当我使用 EmployeeSupervisor 模型类完成上述任务时,实体框架会在数据库中为 EmployeeSupervisor 创建一个对应的表(如预期的那样)。这让我相信我做错了,因为我无法想象每次我想显示来自 2 个不同模型的数据时,我都需要创建一个新的相应模型和表格。

我完成这项工作的方式是否正确?我应该能够使用 Employee 类中定义的导航属性访问主管信息吗?我可以传入多个模型,这样我就不必创建包含来自 2 个单独模型的信息的模型吗?

【问题讨论】:

  • 对我来说,相似之处是如此接近,以至于我会制作一个员工模型并在此模型中拥有一个自引用的 EmployeeID 字段,该字段采用员工主管的 ID。

标签: c# asp.net-mvc entity-framework


【解决方案1】:

创建一个视图模型类,将员工和主管对象包装为属性。在 EF 模型之外执行此操作。

通过 EF 填充属性并将实例传递给您的视图并访问属性以获取值。

【讨论】:

    【解决方案2】:

    查看ViewModels

    您的想法是正确的,但问题是您不应该使用该视图模型创建另一个表。

    确保您的 EmployeeSupervisor 类在您的实体框架的东西之外,该类严格用于显示与视图对应的数据。

    【讨论】:

      【解决方案3】:

      实际上视图只接收一个模型,但这个模型不必是平面的。您的视图模型可以为每个实体包含单独的属性

      public class EmployeeSupervisor
      {
          public Employee Employee { get; set; }
          public Supervisor Supervisor{ get; set; }
      }
      

      在您看来,您与他们的合作方式如下:

         @Html.DisplayFor(model => model.Employee.FirstName)
         @Html.DisplayFor(model => model.Employee.LastName)
         @Html.DisplayFor(model => model.Supervisor.FirstName)
         @Html.DisplayFor(model => model.Supervisor.LastName)
      

      您应该知道的另外一点是,视图不必与实体(在数据库中具有相应表的实体)一起使用。您可以创建一个仅包含视图中使用的属性的 ViewModel。有一些库可以帮助您在 ViewModel 和实体之间进行映射,例如 AutomapperValueInjecter

      例如,如果您需要在视图中仅显示员工和主管的全名,您的视图模型可能如下所示:

      public class EmployeeSupervisorViewModel
      {
          public string EmployeeName { get; set; }
          public string SupervisorName { get; set; }
      }
      

      还有控制器:

          Employee employee = db.Employees.Find(id);
          Supervisor supervisor = db.Supervisors.Find(employee.SupervisorID);
      
          var model = new EmployeeSupervisorViewModel
          {
              EmployeeName =  string.Format("{0} {1}",employee.FirstName, employee.LastName),
              SupervisorName =  string.Format("{0} {1}",supervisor.FirstName, supervisor.LastName),
          };
      
          return View(model);
      

      EmployeeSupervisorViewModel 不是实体,不应该有数据库表。它仅用于 View/Controller 级别,仅包含 View 所需的信息(您要呈现给客户端的信息)

      【讨论】:

        【解决方案4】:

        回答你的问题

        我完成这个的方式正确吗?

        不,您正在寻找的是视图模型。 Rachel Appel 有一篇关于这方面的优秀文章,我强烈建议您阅读 - Use ViewModels to manage data & organize code in ASP.NET MVC applications

        什么是视图模型?

        ViewModel 允许您从一个或多个数据模型(在您的情况下是员工和主管)或源中将多个实体塑造成单个对象,并针对视图的使用和呈现进行了优化。 - 雷切尔阿佩尔

        换句话说,它只是另一个简单的类,就像 Employee 和 Supervisor 通常称为 POCO

        public class EmployeeSupervisorViewModel
        {
            public int EmployeeId { get; set; }
            public string Department { get; set; }
            public string FristName { get; set; }
            public string LastName { get; set; }
            public string SupFirstName { get; set; }
            public string SupLastName { get; set; }
            public string SupEmail { get; set; }
            public string SupPhone { get; set; }
        }
        

        这允许您在Controller 中执行以下操作

                var employee = _db.Employee.Find(id);
                var supervisor = _db.Supervisor.Find(employee.SupervisorID);
        
                var model = new EmployeeSupervisorViewModel()
                {
                    EmployeeId = employee.EmployeeId,
                    Department = employee.Department,
                    FristName = employee.FirstName,
                    LastName = employee.LastName,
                    SupFirstName = supervisor.FirstName,
                    SupLastName = supervisor.LastName,
                    SupEmail = supervisor.Email,
                    SupPhone = supervisor.Phone
                };
                return View(model);
        

        在您的视图中,只需接受视图模型 EmployeeSupervisorViewModel 作为模型并像以前一样对其进行操作。

        @model TimeOffV3.Models.EmployeeSupervisorViewModel
        

        从长远来看,对于较大的视图模型,此映射可能有点乏味。这就是AutoMapper 派上用场的地方。

        最后,我还建议阅读这个post from Jimmy Bogard (How we do MVC – View models),它有一些关于如何创建视图模型的非常好的观点,例如视图和视图模型的 1:1 映射等等。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-16
          • 2014-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多