辞書に渡されるモデル項目の型は ...ですが、この辞書には型のモデル項目が必要です。

c# asp.net-mvc


この質問とコミュニティWikiの回答は、このメタ投稿で説明されているように、多数の未回答の質問を締めくくるために追加されています。


私はいくつかのコードを持っていますが、それが実行されると例外が発生します。

辞書に渡されるモデル項目は 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 がパーシャルに渡されることにも注意してください。この場合、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 を反復処理しているためです。そのため、コレクションをリストに渡すと、コレクション内のアイテムごとにエディターテンプレートが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>



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

私の場合はパーシャルビューを使用していますが、通常のビューで動作します。