传递到字典中的模型项是类型..但是此字典需要类型的模型项

时间:2016-11-02 06:19:49

标签: c# asp.net-mvc

此问题和社区维基回答已添加,以帮助结束this meta post中讨论的众多未回答的问题。

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

  

传递到字典中的模型项是Bar类型,但此字典需要Foo类型的模型项

这是什么意思,我该如何解决?

4 个答案:

答案 0 :(得分:62)

错误意味着您正在导航到其模型被声明为typeof Foo的视图(使用@model Foo),但实际上您传递了一个类型为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]方法初始化该模型并返回其局部视图。 / p>

答案 1 :(得分:4)

观察视图是否具有所需模型:

查看

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

在我的情况下,我使用局部视图但在普通视图中运行

答案 2 :(得分:3)

这个问题已经有了很好的答案,但是在不同的情况下,我遇到了相同的错误:在 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 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,因此,如果将一个集合传递给它,它将为该集合中的每个项目显示一次编辑器模板。 / p>

这是我解决此问题的方法:

将样式带出编辑器模板之外,并进入主视图

@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>

答案 3 :(得分:2)

考虑 map.cshtml 处的部分 Partials/Map.cshtml。这可以从要呈现部分的页面调用,只需使用 <partial> 标记:

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

这是我遇到的最简单的方法之一(虽然我使用的是剃刀页面,但我确定 MVC 也是如此)