Elementul de model trecut în dicționar este de tip … dar acest dicționar necesită un element de model de tip (Programare, C#, Asp.Net Mvc)

user3559349 a intrebat.

Această întrebare și răspunsul din wiki-ul comunității au fost adăugate pentru a ajuta la închiderea numeroaselor întrebări fără răspuns, așa cum se discută în acest meta post.


Am un cod și când se execută, se aruncă o excepție care spune:

Elementul model transmis în dicționar este de tip Bar, dar acest dicționar necesită un element model de tip Foo.

Ce înseamnă acest lucru și cum îl pot rezolva?

Comentarii

  • Am primit această eroare atunci când am folosit return View în loc de return PartialView așa că este ceva ce trebuie verificat.  > Por Richard Housham.
  • <partial name="Partials/Map" model="new Pages.Partials.MapModel()" /> funcționează și ea 🙂 –  > Por d4rk4ng31.
4 răspunsuri

Eroarea înseamnă că navigați către o vizualizare al cărei model este declarat ca typeof Foo (folosind @model Foo), dar, de fapt, i-ai transmis un model care este typeof Bar (rețineți termenul dicționar este utilizat deoarece un model este transmis vizualizării prin intermediul unui ViewDataDictionary).

Eroarea poate fi cauzată de

Transmiterea unui model greșit de la o metodă de controler la o vizualizare (sau vizualizare parțială)

Printre exemplele comune se numără utilizarea unei interogări care creează un obiect anonim (sau o colecție de obiecte anonime) și transmiterea acestuia către vizualizare

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

sau transmiterea unei colecții de obiecte către o vizualizare care așteaptă un singur obiect.

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

Eroarea poate fi identificată cu ușurință la compilare prin declararea explicită a tipului de model în controler pentru a se potrivi cu modelul din vizualizare, în loc să se utilizeze var.

Transmiterea unui model greșit de la o vizualizare la o vizualizare parțială

Având în vedere următorul model

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

și o vizualizare principală declarată cu @model Foo și o vizualizare parțială declarată cu @model Bar, atunci

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

va returna modelul corect către vizualizarea principală. Cu toate acestea, se va lansa o excepție dacă vizualizarea include

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

În mod implicit, modelul transmis către vizualizarea parțială este modelul declarat în vizualizarea principală și trebuie să utilizați

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

pentru a transmite instanța de Bar către vizualizarea parțială. Rețineți, de asemenea, că dacă valoarea lui MyBar este null (nu a fost inițializată), atunci în mod implicit Foo va fi transmisă la vizualizarea parțială, caz în care trebuie să fie

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

Declararea unui model într-un aspect

Dacă un fișier de prezentare include o declarație de model, atunci toate vederile care utilizează prezentarea respectivă trebuie să declare același model sau un model care derivă din acel model.

Dacă doriți să includeți html pentru un model separat într-un layout, atunci în layout, utilizați @Html.Action(...) pentru a apela un fișier [ChildActionOnly] care inițializează modelul respectiv și returnează o vizualizare parțială pentru acesta.

Comentarii

    29

  • +1 pentru „Rețineți, de asemenea, că, dacă valoarea MyBar este nulă (nu a fost inițializată), atunci, în mod implicit, Foo va fi transmisă în vizualizarea parțială, caz în care trebuie să fie”. Notă foarte importantă. –  > Por Smix.
  • Primesc aceeași eroare având un Partial View în cadrul unui Layout, fără un tip de model definit. Vizualizarea parțială se blochează deoarece primește modelul de la pagina de indexare când nu este definit și nici necesar, iar dacă setez modelul parțial la IndexModel, atunci proprietatea ViewData este nulă!??? Cum se poate rezolva acest scenariu? Mutarea parțială în layout funcționează, dar vreau să înțeleg cum funcționează. –  > Por Etienne Charland.
  • M-am lovit de aceeași eroare când vizualizarea mea parțială avea „@page” în partea de sus fără „@model”. eliminarea lui „@page” a rezolvat problema. –  > Por EKanadily.
  • Dacă doriți să trimiteți în mod intenționat un model nul la vizualizarea parțială atunci când Model.MyBar este nul, puteți face acest lucru: @Html.Partial("_Bar", Model.MyBar, new System.Web.Mvc.ViewDataDictionary()) Sursa: https://stackoverflow.com/a/713921/4888725 –  > Por Kirk Grover.
  • @Smix acesta este un comentariu FOARTE util. Tocmai am dat peste asta. –  > Por contactmatt.
Hooman Bahreini

Această întrebare are deja un răspuns grozav, dar m-am lovit de aceeași eroare, într-un scenariu diferit: afișarea unui List într-un EditorTemplate.

Am un model ca acesta:

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

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

Și acesta este modelul meu vedere principală:

@model Foo

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

Și aceasta este bara mea EditorTemplate (Bar.cshtml)

@model List<Bar>

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

Și am primit această eroare:

Elementul de model trecut în dicționar este de tip ‘Bar’, dar acest dicționar necesită un element de model de tip ‘System.Collections.Generic.List`1[Bar]


Motivul pentru această eroare este că EditorFor itera deja List pentru dumneavoastră, astfel încât, dacă îi treceți o colecție, va afișa modelul editorului o dată pentru fiecare element din colecție.

Iată cum am rezolvat această problemă:

Am adus stilurile în afara șablonului editorului și în vizualizarea principală:

@model Foo

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

Și am schimbat EditorTemplate (Bar.cshtml) în următorul lucru:

@model Bar

<label>@Model.BarName</label>

Comentarii

  • Minunat, tocmai m-ai salvat după o jumătate de oră în care m-am scărpinat în cap. Funcționează și pentru ASP.NET Core 3.1 MVC. –  > Por Uwe Keim.
CelzioBR

Observați dacă vizualizarea are modelul necesar:

Vizualizare

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

În cazul meu folosesc o vizualizare parțială, dar rulează în vizualizări normale

Comentarii

  • Ce legătură are acest lucru cu întrebarea? – user3559349
  • @StephenMuecke acest campionat – Elementul de model trecut în dicționar este de tip Bar, dar acest dicționar necesită un element de model de tip Foo –  > Por CelzioBR.
d4rk4ng31

Luați în considerare parțială map.cshtml la Partials/Map.cshtml. Aceasta poate fi apelată din pagina în care urmează să fie redată partea parțială, pur și simplu prin utilizarea instrucțiunii <partial> :

<partial name="Partials/Map" model="new Pages.Partials.MapModel()" />

Aceasta este una dintre cele mai ușoare metode pe care le-am întâlnit (deși folosesc pagini Razor, sunt sigur că același lucru este valabil și pentru MVC)