【问题标题】:Two models in one view in ASP MVC 3ASP MVC 3 中的一个视图中的两个模型
【发布时间】:2011-07-29 20:50:06
【问题描述】:

我有 2 个模型:

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
}
public class Order
{
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

我想在 SINGLE 视图中编辑两个类的对象,所以我需要类似的东西:

@model _try2models.Models.Person
@model _try2models.Models.Order

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x=>x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}

这当然行不通:.cshtml 文件中只允许使用一个“模型”语句。可能有一些解决方法吗?

【问题讨论】:

  • 我的回答对你有帮助吗?
  • 我使用了ViewBag for each in view 为我工作,检查this 以了解多个选项,为我节省了很少的时间,而不是创建视图模型或局部视图

标签: asp.net-mvc-3 viewmodel


【解决方案1】:

创建一个包含两个模型的父视图模型。

public class MainPageModel{
    public Model1 Model1{get; set;}
    public Model2 Model2{get; set;}
}

通过这种方式,您可以在以后轻松添加其他模型。

【讨论】:

  • 使用此解决方案时,请记住,对 Model1 或 Model2 的更改可能会对您的 MainPageModel 产生连锁反应。它们还主要包含比视图真正需要的更多数据。如果您的 MainPage 是其他控制器中已经存在的内容的组合,则从 RenderPartial 切换到 RenderAction 将允许您保持整齐分开。考虑阅读得墨忒耳法则:en.wikipedia.org/wiki/Law_of_Demeter
  • @Andi - 我按照您上面的建议创建了模型。但是当我右键单击控制器并尝试创建 Crud 控制器时,它不起作用?有什么建议?如何为上述模型创建具有自动视图的 crud 控制器?
  • 在我见过的所有解决此问题的方法中,这是最适合我的方法。这是迄今为止最简单的解决方案。
  • 当你问自己“为什么我以前没有想到这一点?”的那一刻很好的解决方案
  • @Andi 如何在控制器中公开相应模型的方法?
【解决方案2】:

您可以使用演示模式http://martinfowler.com/eaaDev/PresentationModel.html

此演示文稿“视图”模型可以同时包含人员和订单,这个新的
类可以是您的视图引用的模型。

【讨论】:

  • 表示模型实际上应该包含所需的数据,这些数据可能来自个人和订单。它不应该真正包含 Person 或 Order 域对象。视图将显示与底层域分离。
【解决方案3】:

如果您喜欢拥有非常扁平的模型,只是为了支持该视图,您应该创建一个特定于该特定视图的模型...

public class EditViewModel
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

许多人使用 AutoMapper 从他们的领域对象映射到他们的平面视图。

视图模型的想法是它只支持视图 - 没有别的。每个视图都有一个,以确保它只包含该视图所需的内容,而不是其他视图所需的大量属性。

【讨论】:

    【解决方案4】:

    另一种从未被谈论过的方式是 在 MSSQL 中创建一个包含您想要呈现的所有数据的视图。然后使用 LINQ to SQL 或其他任何东西来映射它。在您的控制器中将其返回到视图。完毕。

    【讨论】:

      【解决方案5】:

      另一个不需要创建自定义模型的选项是使用Tuple<>

      @model Tuple<Person,Order>
      

      根据安迪的回答,它不像创建一个包含两者的新类那样干净,但它是可行的。

      【讨论】:

      • 在 mvc 3 中它给出错误文件中只允许一个“模型”语句。知道如何解决吗?
      • @GibboK - 我在 MVC3 中使用它就好了。确保您没有两个单独的 @model 行?
      • 您可以通过@Model.Item1.Property@Model.Item2.Property 分别获取PersonOrder 的每个模型的属性
      • 我在我的视图中使用了元组。但是,我无法在我的控制器中获取模型值。但是,当我按照@Andi 的建议使用父视图模型时,我在控制器中获得了模型值。
      • @StephenMuecke - 嗯。我从来没有考虑过,但你是对的。安德鲁的答案的另一个原因是更好的通用答案。当你选择轻量级的替代品(像这样)时,你确实放弃了功能。
      【解决方案6】:

      要使用元组,您需要执行以下操作,在视图中将模型更改为:

      @model Tuple<Person,Order>
      

      要使用@html 方法,您需要执行以下操作,即:

      @Html.DisplayNameFor(tuple => tuple.Item1.PersonId)
      

      @Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id }) |
      

      Item1 表示传递给 Tuple 方法的第一个参数,您可以使用 Item2 访问第二个模型,依此类推。

      您需要在控制器中创建一个元组类型的变量,然后将其传递给视图:

          public ActionResult Details(int id = 0)
          {
              Person person = db.Persons.Find(id);
              if (person == null)
              {
                  return HttpNotFound();
              }
              var tuple = new Tuple<Person, Order>(person,new Order());
      
              return View(tuple);
          }
      

      另一个例子:Multiple models in a view

      【讨论】:

      • 从不在这种情况下使用 Tuple - OP 想要编辑数据,而 Tuple 没有默认构造函数,因此在表单时无法绑定模型已提交
      • 永远不要说永远。这里有点强。
      【解决方案7】:

      你不能在一个视图上声明两个模型,尝试使用Html.Action("Person", "[YourController]") & Html.Action("Order", "[YourController]")

      祝你好运。

      【讨论】:

      • 这是做什么的?
      【解决方案8】:

      只需创建一个包含所有需要信息的视图模型,通常我所做的就是为每个视图创建一个模型,这样我就可以对每个视图进行具体化,或者创建一个父模型并继承它。或者制作一个包含两个视图的模型。

      我个人只会将它们添加到一个模型中,但我就是这样做的:

      public class xViewModel
      {
          public int PersonID { get; set; }
          public string PersonName { get; set; }
          public int OrderID { get; set; }
          public int TotalSum { get; set; }
      }
      
      @model project.Models.Home.xViewModel
      
      @using(Html.BeginForm())
      {
          @Html.EditorFor(x => x.PersonID)
          @Html.EditorFor(x => x.PersonName)
          @Html.EditorFor(x => x.OrderID)
          @Html.EditorFor(x => x.TotalSum)
      }
      

      【讨论】:

        【解决方案9】:

        事实上,有一种方法可以在一个视图上使用两个或多个模型,而无需将它们包装在包含两者的类中。

        以Employee为例:

        @model Employee
        

        实际上被视为。

        @{ var Model = ViewBag.model as Employee; }
        

        因此 View(employee) 方法将您的模型设置为 ViewBag,然后 ViewEngine 正在对其进行投射。

        这意味着,

        ViewBag.departments = GetListOfDepartments();
            return View(employee);
        

        可以像这样使用,

                    @model  Employee
                @{
                        var DepartmentModel = ViewBag.departments as List<Department>;
                }
        

        基本上,您可以将 ViewBag 中的任何内容用作“模型”,因为无论如何它都是这样工作的。我并不是说这在架构上是理想的,但这是可能的。

        【讨论】:

          【解决方案10】:

          希望对你有帮助!!

          我将 ViewBag 用于项目,将模型用于任务,因此我在单个视图中使用两个模型,在控制器中我定义了 viewbag 的值或数据

          List<tblproject> Plist = new List<tblproject>();
                      Plist = ps.getmanagerproject(c, id);
          
                      ViewBag.projectList = Plist.Select(x => new SelectListItem
                      {
                          Value = x.ProjectId.ToString(),
                          Text = x.Title
                      });

          在视图中 tbltask 和 projectlist 是我的两个差异模型

          @{

          IEnumerable<SelectListItem> plist = ViewBag.projectList;
          

          } @模型列表

          【讨论】:

            【解决方案11】:

            好的,每个人都说得通,我把所有的部分都放在这里,以帮助像我这样需要从头到尾解释的新手。

            根据@Andrew 的回答,您创建了包含 2 个类的大类。

            public class teamBoards{
                public Boards Boards{get; set;}
                public Team Team{get; set;}
            }
            

            然后在您的控制器中填充 2 个模型。有时您只需要填写一个。然后在返回时,您引用大模型,它将把里面的 2 带到 View 中。

                        TeamBoards teamBoards = new TeamBoards();
            
            
                    teamBoards.Boards = (from b in db.Boards
                                           where b.TeamId == id
                                           select b).ToList();
                    teamBoards.Team = (from t in db.Teams
                                          where t.TeamId == id
                                      select t).FirstOrDefault();
            
             return View(teamBoards);
            

            在视图的顶部

            @model yourNamespace.Models.teamBoards
            

            然后加载引用大型模型内容的输入或显示:

             @Html.EditorFor(m => Model.Board.yourField)
             @Html.ValidationMessageFor(m => Model.Board.yourField, "", new { @class = "text-danger-yellow" })
            
             @Html.EditorFor(m => Model.Team.yourField)
             @Html.ValidationMessageFor(m => Model.Team.yourField, "", new { @class = "text-danger-yellow" })
            

            而且。 . . . 回到牧场,当 Post 进来时,引用 Big Class:

             public ActionResult ContactNewspaper(teamBoards teamboards)
            

            并利用模型返回的内容:

            string yourVariable = teamboards.Team.yourField;
            

            类中可能有一些 DataAnnotation Validation 内容,并且可能将 if(ModelState.IsValid) 放在保存/编辑块的顶部。 . .

            【讨论】:

              【解决方案12】:

              除了 asp.net 中的一个视图模型,您还可以制作多个局部视图并为每个视图分配不同的模型视图,例如:

                 @{
                      Layout = null;
                  }
              
                  @model Person;
              
                  <input type="text" asp-for="PersonID" />
                  <input type="text" asp-for="PersonName" />
              

              然后是订单模型的另一个局部视图模型

                  @{
                      Layout = null;
                   }
              
                  @model Order;
              
                  <input type="text" asp-for="OrderID" />
                  <input type="text" asp-for="TotalSum" />
              

              然后在你的主视图中加载两个部分视图

              <partial name="PersonPartialView" />
              <partial name="OrderPartialView" />
              

              【讨论】:

                猜你喜欢
                • 2013-08-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-04-21
                • 1970-01-01
                • 2015-09-04
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多