Как использовать несколько моделей в одном представлении для ASP.NET MVC?

Я читал подобные вопросы на 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>
    }

Я попытался сгруппировать классы вместе и использовать частичное представление, но, по-видимому, вы не можете иметь другую модель в частичном представлении, потому что я всегда получаю сообщение об ошибке:

"модельный деталь переданный в словарь тип Системы'.Данных.Лица.В dbset1[AnimalProject.Models.Dog]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[AnimalProject.Модели.Кошка]'."

Итак, как я могу использовать несколько моделей, на мой взгляд, которые оба получают данные, которые я хочу из отдельных таблиц в базе данных?

3 ответов


как насчет создания пользовательского класса модели представления:

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

Заполните эту модель индексом и передайте ее в представление, которое будет ожидать AnimalModel вместо enumerables.

Edit:

наполнение модели:

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

        return View(model);
    }
}

View (я никогда не использовал бритву, поэтому я надеюсь, что это правильно):

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

модель-это просто объект, как и любой другой объект в C# (или VB)

Так можно передать любой объект вы хотите в вид, даже сложные. Если вам нужно представить много вещей, создайте модель представления (модель только для потребностей представления), которая содержит все вещи, которые вы хотите представить, и передайте это представление. Затем из представления вы получаете доступ к отдельным свойствам модели в разных частях представления, чтобы представить их. Примером такого подхода является модель Ладислав Mrnka животных говорили. Тут собаки и кошки enumerables, а затем передаем их в представление. Вы говорите, что ваша модель теперь является этим типом 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, наборам и т. д. непосредственно из вашего представления. Это может быть не лучшая абстракция для доступа к данным, но посмотрите, насколько простым стал ваш контроллер! :) Вы просто бросаете весь мир в поле зрения и позволяете ему решать, какие части выбери и представь... Конечно, это для простых сценариев. Если вам нужны более сложные вещи, вам придется вернуться к пользовательским моделям представлений.


единственное решение этой проблемы, которое я нашел до сих пор, - это бросить обе модели в 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>
}