Елемент моделі, переданий у словник, має тип .. але для цього словника потрібен елемент моделі типу


84

Це запитання та відповідь на спільноту wiki було додано, щоб допомогти закрити численні запитання без відповіді, про які йшлося у цій мета публікації .


У мене є якийсь код, і коли він виконується, він видає виняток, який говорить:

Елемент моделі, переданий у словник, має тип Bar, але для цього словника потрібен елемент моделі типу Foo

Що це означає, і як це виправити?


1
Я отримав цю помилку при використанні return Viewзамість цього, return PartialViewтому це просто потрібно перевірити
Richard Housham

Відповіді:


91

Помилка означає, що ви переходите до подання, модель якого оголошена як 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]метод, який ініціалізує цю модель і повертає для неї частковий вигляд.


26
+1 для "Зауважте також, що якщо значення MyBar є нульовим (не було ініціалізоване), то за замовчуванням Foo буде передано до часткового, і в цьому випадку це має бути". Дуже важлива примітка.
Smix

Я отримую ту ж помилку, маючи частковий вигляд у макеті, не визначивши тип моделі. Частковий вигляд аварійно завершує роботу, оскільки отримує модель зі сторінки індексу, коли жодна не визначена і не потрібна, а якщо для часткової моделі встановлено значення IndexModel, то властивість ViewData має значення null! ?? Як виправити цей сценарій? Переміщення часткового в макет працює, але я хочу зрозуміти, як це працює.
Етьєн Шарленд

Я зіткнувся з тією ж помилкою, коли в моєму частковому поданні вгорі було "@page" без "@model". видалення "@page" вирішило проблему.
EKanadily

1
Якщо ви хочете навмисно надіслати нульову модель до часткового подання, коли Model.MyBarє нульовим, ви можете зробити це: @Html.Partial("_Bar", Model.MyBar, new System.Web.Mvc.ViewDataDictionary()) Джерело: https://stackoverflow.com/a/713921/4888725
Кірк Гровер

6

Це запитання вже має чудову відповідь, але я зіткнувся з тією ж помилкою, за іншим сценарієм: відображення 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.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>

1
Чудово, ти щойно врятував мене через півгодини, почухавши мені голову. Працює і для ASP.NET Core 3.1 MVC.
Уве Кейм,

5

Зверніть увагу, чи має модель подання необхідну модель:

Переглянути

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

У моєму випадку я використовую часткове представлення, але працює в звичайних поданнях


1
Яке відношення це має до питання?

2
@StephenMuecke this champs - Елемент моделі, переданий у словник, має тип Bar, але цей словник вимагає елемент моделі типу Foo
CelzioBR
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.