如何在ASP.NET MVC的一个视图中使用多个模型?

时间:2011-04-29 07:38:00

标签: asp.net-mvc entity-framework

我在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.DbSet 1[AnimalProject.Models.Dog]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable 1 [AnimalProject.Models.Cat]'。“

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

3 个答案:

答案 0 :(得分:13)

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

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

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

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

答案 1 :(得分:3)

模型只是一个对象,就像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>
}

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

答案 2 :(得分:0)

到目前为止,我发现这个问题的唯一解决方法是在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>
}