web-dev-qa-db-fra.com

L'élément de modèle passé dans le dictionnaire est de type .. mais ce dictionnaire nécessite un élément de modèle de type

Cette question et cette réponse du wiki de la communauté ont été ajoutées pour aider à résoudre de nombreuses questions sans réponse, comme indiqué dans cette meta post .


J'ai du code et quand il s'exécute, il lève une exception disant:

L'élément de modèle passé dans le dictionnaire est de type Bar mais ce dictionnaire nécessite un élément de modèle de type Foo.

Qu'est-ce que cela signifie et comment puis-je résoudre le problème?

58
user3559349

L'erreur signifie que vous accédez à une vue dont le modèle est déclaré comme typeof Foo (en utilisant @model Foo), mais vous lui avez en fait passé un modèle qui est typeof Bar (notez le Le dictionnaire term est utilisé car un modèle est transmis à la vue via un ViewDataDictionary).

L'erreur peut être causée par

Passage du mauvais modèle d'une méthode de contrôleur à une vue (ou vue partielle)

Les exemples courants incluent l'utilisation d'une requête qui crée un objet anonyme (ou une collection d'objets anonymes) et le transmet à la vue.

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

ou en passant une collection d'objets à une vue qui attend un seul objet

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

L'erreur peut être facilement identifiée au moment de la compilation en déclarant explicitement le type de modèle dans le contrôleur afin qu'il corresponde au modèle dans la vue plutôt qu'en utilisant var.

Passage du mauvais modèle d'une vue à une vue partielle

Étant donné le modèle suivant

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

et une vue principale déclarée avec @model Foo et une vue partielle déclarée avec @model Bar, puis

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

renverra le bon modèle à la vue principale. Cependant l’exception sera levée si la vue comprend

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

Par défaut, le modèle transmis à la vue partielle est le modèle déclaré dans la vue principale et vous devez utiliser

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

passer l'instance de Bar à la vue partielle. Notez également que si la valeur de MyBar est null (n’a pas été initialisée), alors par défaut Foo sera passé au partiel, auquel cas il devra être

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

Déclarer un modèle dans une mise en page

Si un fichier de présentation inclut une déclaration de modèle, toutes les vues utilisant cette présentation doivent déclarer le même modèle ou un modèle dérivé de ce modèle.

Si vous souhaitez inclure le code HTML d'un modèle distinct dans une présentation, utilisez @Html.Action(...) pour appeler une méthode [ChildActionOnly] initialise ce modèle et renvoie une vue partielle pour celui-ci.

67
user3559349

Observez si la vue a le modèle requis:

Voir

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

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

contrôleur

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

Dans mon cas, j'utilise une vue partielle mais fonctionne dans des vues normales

5
CelzioBR

Cette question a déjà une excellente réponse, mais j'ai rencontré la même erreur, dans un scénario différent: afficher un List dans un EditorTemplate .

J'ai un modèle comme celui-ci:

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

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

Et voici ma vue principale :

@model Foo

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

Et ceci est ma barre EditorTemplate ( Bar.cshtml )

@model List<Bar>

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

Et j'ai eu cette erreur:

L'élément de modèle passé dans le dictionnaire est de type 'Bar', mais ce dictionnaire nécessite un élément de modèle de type 'System.Collections.Generic.List`1 [Bar]


La raison de cette erreur est que EditorFor itère déjà le List pour vous. Ainsi, si vous lui transmettez une collection, le modèle d'éditeur s'affiche une fois pour chaque élément de la collection.

Voici comment j'ai résolu ce problème:

Importé les styles en dehors du modèle d'éditeur et dans la vue principale :

@model Foo

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

Et changé le EditorTemplate ( Bar.cshtml ) pour ça:

@model Bar

<label>@Model.BarName</label>
4
Hooman Bahreini