Элемент модели, переданный в словарь, имеет тип .. но для этого словаря требуется элемент модели типа

87

Этот вопрос и ответ вики сообщества были добавлены, чтобы помочь закрыть множество неотвеченных вопросов, как описано в этом мета-сообщении .


У меня есть код, и когда он выполняется, выдает исключение:

Элемент модели, переданный в словарь, имеет тип Bar, но для этого словаря требуется элемент модели типа Foo.

Что это значит и как это исправить?

Сообщество
источник
1
Я получил эту ошибку при использовании return Viewвместо return PartialView, чтобы просто проверить
Ричард Хаушам

Ответы:

94

Ошибка означает, что вы переходите к представлению, модель которого объявлена ​​как typeof Foo(с помощью @model Foo), но на самом деле вы передали ему модель typeof Bar(обратите внимание, что словарь терминов используется, потому что модель передается в представление через a ViewDataDictionary) .

Ошибка может быть вызвана

Передача неправильной модели из метода контроллера в представление (или частичное представление)

Общие примеры включают использование запроса, который создает анонимный объект (или коллекцию анонимных объектов) и передает его в представление

var model = db.Foos.Select(x => new
{
    ID = x.ID,
    Name = x.Name
};
return View(model); // passes an anonymous object to a view declared with @model Foo

или передача коллекции объектов в представление, которое ожидает один объект

var model = db.Foos.Where(x => x.ID == id);
return View(model); // passes IEnumerable<Foo> to a view declared with @model Foo

Ошибка может быть легко идентифицирована во время компиляции, явно объявив тип модели в контроллере, чтобы соответствовать модели в представлении, а не использовать var.

Передача неправильной модели из представления в частичное представление

Учитывая следующую модель

public class Foo
{
    public Bar MyBar { get; set; }
}

и основное представление, объявленное с, @model Fooи частичное представление, объявленное с @model Bar, затем

Foo model = db.Foos.Where(x => x.ID == id).Include(x => x.Bar).FirstOrDefault();
return View(model);

вернет правильную модель в главный вид. Однако исключение будет выдано, если представление включает

@Html.Partial("_Bar") // or @{ Html.RenderPartial("_Bar"); }

По умолчанию модель, переданная в частичное представление, является моделью, объявленной в основном представлении, и вам необходимо использовать

@Html.Partial("_Bar", Model.MyBar) // or @{ Html.RenderPartial("_Bar", Model.MyBar); }

чтобы передать экземпляр Barв частичное представление. Также обратите внимание, что если значение MyBarравно null(не было инициализировано), то по умолчанию Fooбудет передано в партиал, и в этом случае оно должно быть

@Html.Partial("_Bar", new Bar())

Объявление модели в макете

Если файл макета включает объявление модели, то все представления, использующие этот макет, должны объявлять одну и ту же модель или модель, производную от этой модели.

Если вы хотите включить html для отдельной модели в макет, то в макете используйте @Html.Action(...)для вызова [ChildActionOnly]метода, инициализирует эту модель и возвращает для нее частичное представление.

Стивен Мьюке
источник
27
+1 для «Обратите внимание, что если значение MyBar равно нулю (не было инициализировано), то по умолчанию Foo будет передано в партиал, и в этом случае он должен быть». Очень важное замечание.
Smix 08
Я получаю ту же ошибку при наличии частичного представления в макете без определенного типа модели. При частичном представлении происходит сбой, потому что он получает модель со страницы индекса, когда она не определена и не нужна, и если я устанавливаю частичную модель на IndexModel, тогда свойство ViewData имеет значение null! ?? Как исправить этот сценарий? Перемещение части в макет действительно работает, но я хочу понять, как это работает.
Этьен
Я столкнулся с той же ошибкой, когда в моем частичном представлении было «@page» вверху без «@model». удаление "@page" решило проблему.
EKanadily 07
1
Если вы хотите намеренно отправить нулевую модель в частичное представление, когда оно Model.MyBarравно null, вы можете сделать это: @Html.Partial("_Bar", Model.MyBar, new System.Web.Mvc.ViewDataDictionary()) Источник: https://stackoverflow.com/a/713921/4888725
Кирк Гровер,
@Smix это ОЧЕНЬ полезный комментарий. Просто столкнулся с этим.
contactmatt
7

На этот вопрос уже есть отличный ответ, но я столкнулся с той же ошибкой в ​​другом сценарии: отображение a Listв EditorTemplate .

У меня такая модель:

public class Foo
{
    public string FooName { get; set; }
    public List<Bar> Bars { get; set; }
}

public class Bar
{
    public string BarName { get; set; }
}

И это мой основной взгляд :

@model Foo

@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })  
@Html.EditorFor(m => m.Bars)

А это мой шаблон Bar EditorTemplate ( Bar.cshtml )

@model List<Bar>

<div class="some-style">
    @foreach (var item in Model)
    {
        <label>@item.BarName</label>
    }
</div>

И я получил такую ​​ошибку:

Элемент модели, переданный в словарь, имеет тип 'Bar', но для этого словаря требуется элемент модели типа 'System.Collections.Generic.List`1 [Bar]


Причина этой ошибки в том, EditorForчто Listдля вас уже выполняется итерация , поэтому, если вы передадите ему коллекцию, он отобразит шаблон редактора один раз для каждого элемента в коллекции.

Вот как я исправил эту проблему:

Перенес стили за пределы шаблона редактора и в главное представление :

@model Foo

@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })  
<div class="some-style">
    @Html.EditorFor(m => m.Bars)
</div>

И изменил EditorTemplate ( Bar.cshtml ) на это:

@model Bar

<label>@Model.BarName</label>
Hooman Bahreini
источник
1
Потрясающе, ты только что спас меня после получаса почесывания головы. Также работает с ASP.NET Core 3.1 MVC.
Уве Кейм
6

Обратите внимание, есть ли у вида требуемая модель:

Посмотреть

@model IEnumerable<WFAccess.Models.ViewModels.SiteViewModel>

<div class="row">
    <table class="table table-striped table-hover table-width-custom">
        <thead>
            <tr>
....

Контроллер

[HttpGet]
public ActionResult ListItems()
{
    SiteStore site = new SiteStore();
    site.GetSites();

    IEnumerable<SiteViewModel> sites =
        site.SitesList.Select(s => new SiteViewModel
        {
            Id = s.Id,
            Type = s.Type
        });

    return PartialView("_ListItems", sites);
}

В моем случае я использую частичное представление, но работаю в обычных представлениях

CelzioBR
источник
1
При чем тут вопрос?
2
@StephenMuecke this champs - Элемент модели, переданный в словарь, имеет тип Bar, но для этого словаря требуется элемент модели типа Foo
CelzioBR