MVC Razor動的モデル、「オブジェクト」には「PropertyName」の定義が含まれていません


106

RazorビューエンジンでMVC 3を使用します。私はこのビューを持っています:

@model dynamic
@{
    var products = (List<ListItemBaseModel>)Model.Products;
    var threshold = (int)(Model.Threshold ?? 1);
    var id = Guid.NewGuid().ToString();
}

次のコードを使用して別のビューから呼び出されます。

@Html.Partial("PartialViewName", new { Products = Model, Threshold = 5 })

両方のビューで、デバッグしてモデルを見ると、正しいオブジェクトが含まれているようです。コードを実行すると、 "var products ="行に次のエラーが表示されます。

「オブジェクト」には「製品」の定義が含まれていません

なぜ私はそのエラーが発生するのですか?繰り返しますが、デバッグモードでモデルオブジェクトを見ると、問題はありません(製品としきい値の2つのプロパティがあります)。


回答:


150

匿名クラスのインスタンスをビューモデルとして渡していますか?これを試してみたところ(CSHTMLの動的ビューモデル)、匿名クラスを使用すると同じエラーが発生しましたが、名前付きクラスを作成すると問題なく動作しました。私は検索しましたが、どこにも記載されているこの文書を見ていません。

// error
return View(new { Foo = 1, Bar = "test" });

// worked
return View(new TestClass { Foo = 1, Bar = "test" });

編集#1:

David Ebboによると、匿名型はとしてコンパイルされるため、動的型付きビューに匿名型を渡すことはできませんinternal。CSHTMLビューは別のアセンブリにコンパイルされるため、匿名型のプロパティにアクセスできません。

編集#2:

David Ebboがこの説明を基に投稿を編集しました。

注(2011年12月22日):MVC 3が動的を直接サポートするようになったため、以下の手法は不要になりました。この投稿は、実際に機能をMVCに統合することにつながったものです!


1
編集は知っておくと便利です。私は同じ問題を抱えていて、そこでのWTFを理解していませんでした。説明ありがとう。
Yanick Rochon 2013年

18
編集#2は、現在(MVC> 3)が「エラー」でマークされた行を実行できることを示唆していますか?return View(new { Foo = 1, Bar = "test" });?MVC 4を使用しているにもかかわらず、「オブジェクトにFooの定義が含まれていない」というメッセージが表示される
スポーツ

@sports me too ...回避策を見つけましたか?(ToExpando1つの横)
アレックス

2
そのため、今2018年、ASP.NET Core 2.1とRazorビューを使用しているときに、元の質問のエラーが依然として私を悩ませています。したがって、MVC 3がこれを修正することについてのこの話が何であるかはわかりません。
アンドリューアーノット2018

41

.NET 4.0では、匿名型を簡単にExpandoObjectsに変換できるため、変換自体のオーバーヘッドによってすべての問題が修正されます。ここをチェック


どういたしまして。多分これはM $をキックして匿名型をより使いやすくします
Adaptabi

これはパーシャルにも当てはまりますか?パーシャルを動的にディスパッチできないというエラーが発生しました...
John Bubriski

1
何のパーシャル?例を提供できますか?
Adaptabi 2012年

27

これは、内部プロパティを持つ匿名型とは関係ありません

匿名型をビューから部分ビューに渡すことは完全に可能です

今日も同じ問題が発生しましたが、匿名型とその固有のinternalプロパティを渡す問題とは(直接)関係がありませんでした。

そのため、OPの質問に関しては、@ Lucasによる回答は無関係です-回避策は機能しますが。

OPの質問では、匿名タイプがアセンブリXのビューからアセンブリXのパーシャルに渡されているため、David Ebboが匿名タイプの内部にあるプロパティについて概説した問題は重要ではありません。ビュー用にコンパイルされた型、部分型、匿名型はすべて同じアセンブリに含まれています。

では、ビューからパーシャルへの匿名型の突然の失敗の原因は何ですか?

少なくとも私の状況では、解決できないモデルタイプを指定するSAME FOLDERの別のビューが原因であることがわかりました。ビューは実行時にコンパイルされるため、実行時にビューのコンパイルに失敗すると、動的型のコンパイルに失敗し、パーシャルは単にを受け取ることになりobjectます。何が起こっているのかはすぐにはわかりませんが、OP固有の例(および私の例)では、これが問題の原因である可能性が高いです。

モデルタイプは正しいが、ビューの別の部分がコンパイルされない場合、匿名タイプは同じ方法で影響を受けないことに注意してください。これは、Razorがビューのコンポーネント部分の動的コンパイルをどのように分割するかにかかっているはずです。

問題のあるビューを修正したら、ソリューション全体を再ビルドするか、プロジェクトがクリーンで再ビルドされてから、修正されているかどうかを確認します。

これに再び巻き込まれないようにするには、これをcsprojファイルに追加して、Razorビューのコンパイル時のコンパイルを有効にします。

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

2
これは私の問題を修正しました-"@model dynamic"を使用することは最初は正しい修正のように見えましたが、実際には間違った道をたどっていました。
クリムボ2014年

私はソリューションをクリーンアップして再構築し、エラーはなくなりました。
maxbeaudoin 2014

MVC 3以降、動的ビューモデルに対するMVCのサポートを反映するように回答を更新しました
Lucas

時々ビューのコンパイルを有効にすることは、巨大なコードベースでは常に役立ちます。明らかに問題のすべての種類、タイプミス、それはなどを導入し、強力なタイピングにT4MVCのおかげでエラー
デニス・ザ・メナス

ああ、そうです:ビューからパーシャルへのパスについて話していることに気づきました。私の問題であるコントローラーからビューへではありません。
mwardm

9

ソリューションの任意の場所に次のクラスを追加します(システム名前空間を使用するので、参照を追加することなくすぐに使用できます)-

    namespace System
    {
        public static class ExpandoHelper
        {
            public static ExpandoObject ToExpando(this object anonymousObject)
            {
                IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
                IDictionary<string, object> expando = new ExpandoObject();
                foreach (var item in anonymousDictionary)
                    expando.Add(item);
                return (ExpandoObject)expando;
            }

        }
    }

モデルをビューに送信したら、それをExpandoに変換します。

    return View(new {x=4, y=6}.ToExpando());

1
最初の動的オブジェクトを作成し、ExpandoObject ...だけではなく、ExpandoObjectを作成..作成するために、私にunnecssaryオーバーヘッドのように思える
Baz1nga

@ Baz1ngaできません... new Expando(){prop = value、...}。これは問題を引き起こします。Json.NetのJObjectを同様の使い方で使用しています。
Tracker1

3
HtmlHelperがそこにあるのは間違っています... public static ExpandoObject ToExpando(this object o){IDictionary <string、object> expando = new ExpandoObject(); foreach(var propertyInfo in o.GetType()。GetProperties()){expando.Add(new KeyValuePair <string、object>(propertyInfo.Name、propertyInfo.GetValue(o、index:null))); } return(ExpandoObject)expando; }
erlando 2012

6

dynamic部分ビュー内でモデルタイプを使用する代わりに。

@ViewData.Eval("foo")代わりにを使用して、匿名オブジェクトの属性を呼び出すことができます@Model.foo

その後@Model dynamic、ビューから削除できます。

Facebook Social Comments Integrationのビュー間でいくつかの属性を渡すときに、この問題に最近遭遇しました。コード例:

Html.RenderPartial(@"Layouts/Partials/_Comments", new {currentUrl = Model.CurrentPage.GetAbsoluteUrl(), commentCount = 5 });

次に、私の見解では、このdivがありました:

<div class="fb-comments" data-href="@ViewData.Eval("currentUrl")" data-numposts="@ViewData.Eval("commentCount")" data-width="100%"></div>

0

回避策を実装していないため、このエラーが発生するかどうかはわかりません。部分的なビューで同じエラーが発生しました。解決策は、ビルドをクリーンアップして再ビルドすることでした。構文が正しい場合、コードは機能しますが、かみそりエンジンがコード変更を正しく更新していない可能性があります。


0

辞書を使用してこの問題を回避しました。

 @Html.Partial("_Partial", new Dictionary<string, string> { { "Key1", "Val1" }, { "Key2", "Val2" }, { "Key3", "Val3" } });

-6

dynamicタイプを使用するには、Microsoft.CSharpアセンブリを参照する必要があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.