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

c# asp.net-mvc


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


У меня есть какой-то код,и когда он выполняется,он бросает изречение:

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

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





Answer 1 Stephen Muecke


Ошибка означает, что вы переходите к представлению, модель которого объявлена ​​как typeof Foo (с помощью @model Foo ), но вы фактически передали ему модель, которая является typeof Bar (обратите внимание, что словарь терминов используется, потому что модель передается в представление через 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(...) используйте @ Html.Action (...) для вызова метода [ChildActionOnly] , который инициализирует эту модель и возвращает для нее частичное представление.




Answer 2 CelzioBR


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

View

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

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

Controller

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

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




Answer 3 Hooman Bahreini


На этот вопрос уже есть отличный ответ, но я столкнулся с той же ошибкой в ​​другом сценарии: отображение 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>