ディクショナリに渡されるモデルアイテムのタイプは..ですが、このディクショナリにはタイプのモデルアイテムが必要です


87

この質問とコミュニティウィキの回答は、このメタ投稿で説明されているように、多数の未回答の質問を閉じるのに役立つように追加されました。


私はいくつかのコードを持っています、そしてそれが実行されるとき、それは言う例外を投げます:

ディクショナリに渡されるモデルアイテムはタイプBarですが、このディクショナリにはタイプFooのモデルアイテムが必要です。

これはどういう意味ですか、どうすれば修正できますか?


1
return View代わりに使用するとこのエラーが発生したreturn PartialViewので、確認するだけです
RichardHousham18年

回答:


94

このエラーは、モデルが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部分ビューに渡します。の値MyBarnull(初期化されていない)の場合、デフォルトでFooパーシャルに渡されることにも注意してください。この場合、次のようにする必要があります。

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

レイアウトでモデルを宣言する

レイアウトファイルにモデル宣言が含まれている場合、そのレイアウトを使用するすべてのビューは、同じモデル、またはそのモデルから派生したモデルを宣言する必要があります。

別のモデルのhtmlをレイアウトに含め、次にレイアウトに含める場合は、を使用@Html.Action(...)して[ChildActionOnly]メソッドを呼び出し、そのモデルを初期化し、そのモデルの部分ビューを返します。


27
「MyBarの値がnull(初期化されていない)の場合、デフォルトでFooがパーシャルに渡されることに注意してください。この場合、Fooはパーシャルに渡される必要があります」。非常に重要な注意。
スミックス2018年

モデルタイプが定義されていないレイアウト内に部分ビューがあると、同じエラーが発生します。部分ビューは、定義も必要もないときにインデックスページからモデルを受け取るためにクラッシュします。部分モデルをIndexModelに設定すると、ViewDataプロパティがnullになります!?? このシナリオを修正するにはどうすればよいですか?パーシャルをレイアウトに移動することは機能しますが、それがどのように機能するかを理解したいと思います。
エティエンヌチャーランド

部分ビューの上部に「@model」のない「@page」があると、同じエラーが発生しました。「@page」を削除すると問題が解決しました。
EKanadily

1
あなたは時に意図的に部分図にヌルモデルを送信する場合はModel.MyBarnullがある、あなたはこれを行うことができます。 @Html.Partial("_Bar", Model.MyBar, new System.Web.Mvc.ViewDataDictionary()) 出典:https://stackoverflow.com/a/713921/4888725
カークグローバー

@Smixこれは非常に役立つコメントです。ちょうどこれに遭遇しました。
contactmatt

7

この質問にはすでにすばらしい答えがありますが、別のシナリオで同じエラーが発生しListました。EditorTemplateにを表示することです

私はこのようなモデルを持っています:

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)

そしてこれは私のBarEditorTemplateBar.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ため、コレクションを渡すと、コレクション内のアイテムごとにエディターテンプレートが1回表示されるためです。

これが私がこの問題を修正した方法です:

エディターテンプレートの外に、スタイルを持ち込みました メインビューに

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

1
素晴らしい、あなたはちょうど私の頭を掻いた30分後に私を救った。ASP.NET Core 3.1MVCでも機能します。
UweKeim20年

6

ビューに必要なモデルがあるかどうかを確認します。

見る

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

私の場合、部分ビューを使用しますが、通常のビューで実行されます


1
これは質問と何の関係がありますか?

2
@StephenMuecke this champs-ディクショナリに渡されるモデルアイテムはタイプBarですが、このディクショナリにはタイプFooのモデルアイテムが必要です
CelzioBR 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.