【问题标题】:How to use multiple models in one view for ASP.NET MVC?如何在一个视图中为 ASP.NET MVC 使用多个模型?
【发布时间】:2011-04-29 07:37:59
【问题描述】:

我已经阅读了关于 SO 的类似问题,但似乎无法弄清楚这个问题,这是特定于 DBContext 对象的(我认为)。这里有一些虚拟代码来说明。

我的 Index() 操作中有以下代码:

    public ActionResult Index()
    {
        AnimalDBContext db = new AnimalDBContext();

        return View(db.Dogs);
    }

我的模型有以下代码:

    public class Dog
    {
        public int ID { get; set; }
        public string name { get; set; }
        public string breed { get; set; }
    }

    public class AnimalDBContext : DbContext
    {
        public DbSet<Dog> Dogs { get; set; }
    }

在我看来,我有以下几点:

@model IEnumerable<AnimalProject.Models.Dog>
    @foreach (var d in Model)
    {
    <h3>@d.name</h3>
    <h2>@d.breed</h2>
    }

一切都很好,视图将遍历我数据库中的每条狗。但是,我在同一个视图中有另一个表中的另一组 DBContext 数据。我也希望能够为该表枚举数据库中的每个项目。

这就是我想要的,如果你明白我的意思:

@model IEnumerable<AnimalProject.Models.Dog>
@model IEnumerable<AnimalProject.Models.Cat>
    @foreach (var d in Dog)
    {
    <h3>@d.name</h3>
    <h2>@d.breed</h2>
    }
    @foreach (var c in Cat)
    {
    <h3>@c.name</h3>
    <h2>@c.breed</h2>
    }

我尝试将类分组在一起并使用局部视图,但显然你不能在局部视图中使用不同的模型,因为我总是收到错误消息:

"模型项传入 字典是类型 'System.Data.Entity.DbSet1[AnimalProject.Models.Dog]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[AnimalProject.Models.Cat]'。”

那么,如何在我的视图中使用多个模型,它们都从数据库中的不同表中获取我想要的数据?

【问题讨论】:

    标签: asp.net-mvc entity-framework


    【解决方案1】:

    如何创建自定义视图模型类:

    public AnimalModel
    {
        public IEnumerable<Dog> Dogs { get; set; }
        public IEnumerable<Cat> Cats { get; set; }
    } 
    

    在 Index 中填充此模型并将其传递给期望 AnimalModel 而不是枚举的视图。

    编辑:

    填充模型:

    public ActionResult Index()
    {
        using (var db = new AnimalDBContext())
        {
            var model = new AnimalModel 
            {
                Dogs = db.Dogs.ToList(),
                Cats = db.Cats.ToList()
            };
    
            return View(model);
        }
    }
    

    查看(我从未使用过 Razor,所以我希望这是正确的):

    @model AnimalProject.Models.AnimalModel
    @foreach (var d in Model.Dogs)
    {
      <h3>@d.name</h3>
      <h2>@d.breed</h2>
    }
    @foreach (var c in Model.Cats)
    {
      <h3>@c.name</h3>
      <h2>@c.breed</h2>
    }
    

    【讨论】:

    • 我刚试过这个,也许你可以详细说明一下。如果我在视图顶部的@model 中指定AnimalModel 类,则在我的索引中填充AnimalModel 类,当我尝试@foreach(模型中的var d)时,我无法深入三层。所以,如果我写@d.Dogs,这就是我得到的全部,我不能写@d.Dogs.name,因为Dogs 也必须被枚举。这有意义吗?
    • 您必须遍历模型的属性:foreach(var d in Model.Dogs)
    • 当我尝试这样做并添加句点(模型)时,Dogs 不是视图中的选项。它只显示 Aggregate、All、Any... 等。也许我没有正确填写模型。由于某种原因,在 MVC 中,我无法使用 foreach 迭代任何类的属性。
    • 你是如何在视图中注册AnimalModel的?看起来你已经注册了动物模型集合。
    • 像这样:@model IEnumerable
    【解决方案2】:

    模型只是一个对象,就像 C#(或 VB)中的任何其他对象一样

    所以你可以将任何你想要的对象传递给视图,甚至是复杂的对象。如果您需要呈现很多东西,那么创建一个视图模型(仅用于视图需要的模型),其中包含您想要呈现的所有内容并将其传递给视图。然后,从视图中,您可以在视图的不同部分访问模型的各个属性,以呈现它们。这种方法的一个例子是 Ladislav Mrnka 谈到的动物模型。你把狗和猫的可枚举项放在那里,然后将它传递给视图。你告诉视图你的模型现在是这个 AnimalModel 类型等等......

    因此,由于模型只是一个对象,并且如果您懒得不想创建另一个自定义视图模型,那么您可以将整个 dbcontext 作为模型传递给这样的视图。

    控制器

    public ActionResult Index()
    {
       return View(new AnimalDBContext()); // We pass a new instance of the dbcontext to the view
    }
    

    查看

    @model AnimalProject.AnimalDBContext // we declare that our model is of type AnimalDBContext 
    @foreach (var d in Model.Dogs) // We reference the dbcontext's sets directly
    {
      <h3>@d.name</h3>
      <h2>@d.breed</h2>
    }
    @foreach (var c in Model.Cats) // We reference the dbcontext's sets directly
    {
      <h3>@c.name</h3>
      <h2>@c.breed</h2>
    }
    

    现在您已经向您的视图声明您的“模型”对象将是 AnimalDBContext 因此,您可以直接从您的视图中访问所有 AnimalDBContext 的属性、集合等。它可能不是数据访问的最佳抽象,但看看你的控制器变得多么简单! :) 您只需将整个世界放入视图中,让它决定选择和呈现哪些部分......当然这是针对简单场景的。如果您想要更复杂的东西,您最终将不得不退回到自定义视图模型。

    【讨论】:

      【解决方案3】:

      到目前为止,我发现解决此问题的唯一方法是将两个模型夹在 ViewBag 中,然后为仅使用一个模型的零件渲染部分视图。当然,它只有在部分视图是可分离的情况下才有效——就像你的情况一样。与直接访问ViewBag 的内容相比,这允许强类型化的部分视图。

      解决方案类似于 Ufuk 在此处的回答。首先将数据从控制器中放入ViewBag

      ViewBag.Dogs = db.Dogs;
      ViewBag.Cats = db.Cats;
      

      然后从视图中渲染局部视图:

      @Html.Partial("_ListDogs", ViewBag.Dogs)
      @Html.Partial("_ListCats", ViewBag.Cats)
      

      每个部分视图都将遵循以下内容(例如_ListDogs.cshtml):

      @model IEnumerable<AnimalProject.Models.Dog>
      @foreach (var d in Model)
      {
          <h3>@d.name</h3>
          <h2>@d.breed</h2>
      }
      

      【讨论】:

      • 这看起来很有希望,一切都已正确设置,但是当我指定 @Html.Partial("_ListDogs", ViewBag.Dogs) 时出现此错误:System.Web.Mvc.HtmlHelper'没有名为“Partial”的适用方法,但似乎具有该名称的扩展方法。扩展方法不能动态调度。考虑强制转换动态参数或在没有扩展方法语法的情况下调用扩展方法。
      • 查看stackoverflow.com/questions/4047543/… 以及第一个答案中的 SO 链接。将 ViewBag.Dogs 转换为 object 让我的问题消失了,但我不确定是否应该将其转换为 IEnumerable&lt;AnimalProject.Models.Dog&gt;
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 2015-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多