【问题标题】:The model item passed into the dictionary is of type .. but this dictionary requires a model item of type传入字典的模型项的类型是 .. 但是这个字典需要一个类型的模型项
【发布时间】:2017-03-15 09:22:22
【问题描述】:

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


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

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

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

【问题讨论】:

  • 我在使用 return View 而不是 return PartialView 时遇到了这个错误,所以需要检查一下
  • <partial name="Partials/Map" model="new Pages.Partials.MapModel()" /> 也可以:)

标签: c# asp.net-mvc


【解决方案1】:

错误意味着您正在导航到一个视图,其模型声明为 typeof Foo(通过使用 @model Foo),但您实际上传递给它的模型是 typeof Bar(注意术语 dictionary 之所以被使用,是因为模型是通过 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())

在布局中声明模型

如果布局文件包含模型声明,则使用该布局的所有视图都必须声明相同的模型,或从该模型派生的模型。

如果您想在 Layout 中包含单独模型的 html,请在 Layout 中使用 @Html.Action(...) 调用 [ChildActionOnly] 方法初始化该模型并为其返回部分视图。

【讨论】:

  • +1 表示“另请注意,如果 MyBar 的值为 null(尚未初始化),则默认情况下 Foo 将传递给部分,在这种情况下,它需要是”。非常重要的说明。
  • 我在布局中有一个局部视图,但没有定义模型类型,我遇到了同样的错误。部分视图崩溃是因为它从索引页面接收模型时没有定义也不需要,如果我将部分模型设置为 IndexModel,那么 ViewData 属性为空!??如何解决这种情况?将部分移动到布局中确实有效,但我想了解它是如何工作的。
  • 当我的局部视图顶部有“@page”而没有“@model”时,我遇到了同样的错误。删除“@page”解决了这个问题。
  • 如果你想在Model.MyBar为空的情况下有意发送一个空模型到局部视图,你可以这样做:@Html.Partial("_Bar", Model.MyBar, new System.Web.Mvc.ViewDataDictionary())来源:https://stackoverflow.com/a/713921/4888725
  • @Smix 这是一个非常有用的评论。刚碰到这个。
【解决方案2】:

这个问题已经有了很好的答案,但我在不同的场景中遇到了同样的错误:在 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)

这是我的酒吧 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,所以如果你向它传递一个集合,它会为集合中的每个项目显示一次编辑器模板。

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

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

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

【讨论】:

  • 太棒了,你挠了半个小时才救了我。也适用于 ASP.NET Core 3.1 MVC。
【解决方案3】:

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

查看

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

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

【讨论】:

  • 这和问题有什么关系?
  • @StephenMuecke this champs - 传入字典的模型项是 Bar 类型,但此字典需要 Foo 类型的模型项
【解决方案4】:

考虑Partials/Map.cshtml 处的部分map.cshtml。这可以从要呈现部分的页面调用,只需使用&lt;partial&gt; 标签:

&lt;partial name="Partials/Map" model="new Pages.Partials.MapModel()" /&gt;

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

【讨论】:

    【解决方案5】:

    首先,您需要将模型的 IEnumerable 版本返回到列表视图。

    @model IEnumerable<IdentityManager.Models.MerchantDetail>
    

    其次,您需要从数据库中返回一个列表。我是通过 SQL Server 做的,所以这是我开始工作的代码。

        public IActionResult Merchant_Boarding_List()
            List<MerchantDetail> merchList = new List<MerchantDetail>();
            var model = new MerchantDetail();
    
            try
            {
                using (var con = new SqlConnection(Common.DB_CONNECTION_STRING_BOARDING))
                {
                    con.Open();
                    using (var command = new SqlCommand("select * from MerchantDetail md where md.UserGUID = '" + UserGUID + "'", con))
                    {
                        using (SqlDataReader reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                model.biz_dbaBusinessName = reader["biz_dbaBusinessName"].ToString();
                                merchList.Add(model);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
    
            return View(merchList);
    

    【讨论】:

      【解决方案6】:

      将从控制器方法填充的模型值传递给视图

       public async Task<IActionResult> Index()
       {
         //Getting Data from Database
         var model= await _context.GetData();
      
         //Selecting Populated Data from the Model and passing to view
         return View(model.Value);
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-05
        相关资源
        最近更新 更多