传入字典中的模型项的类型为...,但这个字典需要一个模型项的类型为

c# asp.net-mvc


已添加此问题和社区Wiki答案,以帮助解决本meta post中讨论的许多未回答的问题。


我有一些代码,当它执行时,它会抛出一个异常说。

传入字典的模型项是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(...) 调用 [ChildActionOnly] 方法初始化该模型并返回其部分视图。




Answer 2 Hooman Bahreini


这个问题已经有了一个不错的答案,但是在不同的情况下,我遇到了相同的错误:在EditorTemplate中显示一个 List

我有一个这样的模型。

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 EditorTemplateBar.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>

并将EditorTemplateBar.cshtml)更改为此:

@model Bar

<label>@Model.BarName</label>



Answer 3 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);
}

在我的案例中,我使用的是部分视图,但在正常视图中运行。