nullモデルのrenderpartialが間違ったタイプを渡される


198

ページがあります:

<%@ Page Inherits="System.Web.Mvc.View<DTOSearchResults>" %>

そしてその上で、次のこと:

<% Html.RenderPartial("TaskList", Model.Tasks); %>

DTOオブジェクトは次のとおりです。

public class DTOSearchResults
{
    public string SearchTerm { get; set; }
    public IEnumerable<Task> Tasks { get; set; }

そしてここに部分的です:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Task>>" %>

Model.Tasksがnullでない場合、すべてが正常に機能します。ただし、そのnullの場合、次のようになります。

ディクショナリに渡されたモデルアイテムのタイプは「DTOSearchResults」ですが、このディクショナリにはタイプ「System.Collections.Generic.IEnumerable`1 [Task]」のモデルアイテムが必要です。

使用するオーバーロードを知らないようにする必要があると考えたので、これを明示的に(下記を参照)行いましたが、それでも同じ問題が発生します!

<% Html.RenderPartial("TaskList", (object)Model.Tasks, null); %>

私はnullをチェックするか、nullを渡さなくてもこれを回避できることを知っていますが、それは重要ではありません。なぜこうなった?

回答:


349

Andrew私があなたが得ている問題は、あなたが渡すモデルがnullであるときに、部分ビューに対して呼び出し(ビュー)のモデルを使用するRenderPartialメソッドの結果だと思います。

<% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary()); %>

それは役に立ちますか?


16
人々の時間を節約しています。これで髪を抜いていた。
James Gregory、

3
彼らがnullモデルをサポートし、ページモデルを渡す理由を理解しましたが、オーバーロードによってそれらを処理できませんでした。@ Html.Render( "donkeys")は@ Html.Render( "donkeys"、couldbenull)とは異なります
Phil Strong

19
私は「問題」を追加して、あなたが同意する場合、私は、これは非常に直感に反することに投票を見つける:aspnet.codeplex.com/workitem/8872
PBZ

3
このソリューションでは、プライマリモデルのViewDataが部分ビューで失われたため、部分ビューのValidationSummaryが機能しないことがわかりました。これを解決するために、ここで指定した答えstackoverflow.com/a/12037580/649497を使用しました 。
BruceHill 2013

5
既存のViewDataを渡す必要があります:new ViewDataDictionary(ViewData)
ScottE

48

@myandmycodeの答えは良いですが、少し短い方が良いでしょう

<% Html.RenderPartial("TaskList", new ViewDataDictionary(Model.Tasks)); %>

これViewDataDictionaryは、がモデルを保持するものであり、コンストラクタパラメータとしてモデルを受け入れることができるため機能します。これは基本的に「全体」のビューデータディクショナリを渡しますが、これにはもちろんnullの可能性があるモデルのみが含まれます。


2
@jcmcbeth:えーっと、いや、そうではありません...この正確なコードをnullで正常に使用しました。
コンフィギュレー

1
@jcmcbeth:使用していnew ViewDataDictionary(null)ますか?ViewDataDictionaryそれはおそらくnullを受け入れないパラメーターを持つ別のオーバーロードを選択するためです。
コンフィギュレー

1
ViewBagプロパティを使用すると、間違ったコンストラクターが呼び出されるように見えます。それが動的タイプを取り、それがオブジェクトに対するViewDataDictionaryであると想定する方法は、私には意味がありませんが、それがしているように見えます。正しいコンストラクターを選択するには、それをオブジェクトにキャストする必要があります。
Joel McBeth、2011

1
@jcmcbeth:動的型を介して呼び出すと、実際の値を指定した場合と同じように使用されます。値がの場合、それはnull呼び出しnew ViewDataDictionary(null)と同じであり、最も具体的なオーバーロードが呼び出されます。
コンフィギュレー

1
このように使用すると、dictionairyエラーはなくなります。nullの Html.RenderPartial("TaskList", new ViewDataDictionary(model: Model.Tasks))場合、間違ったコンストラクタを使用しています。
Filip Cornelissen

26

渡したモデルのプロパティがnullの場合、MVCは意図的に「親」モデルに戻ります。どうやら、MVCエンジンはnullモデル値を前のモデル値を使用する意図として解釈します。

ここで少し詳細:ASP.NET MVC、厳密に型指定されたビュー、部分的なビューパラメーターの不具合


1
これを奇妙な振る舞いとして扱うだけでなく、実際に問題を説明しようとするための+1
YavgenyP

うん、これは私に起こっていて、上記はそれを修正しませんでした、それは私に私の実際のエラーに関するもう少しの情報を与えました。
キャンバス

20

部分ビューで以前のViewDataを失いたくない場合は、次の方法を試してください。

<% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary(ViewData){Model = null});%>

1
これは質問に答えていないようです。
ジョンサンダース

6
+1実際には動作します。それは基本的にここで紹介する同じ考えであるstackoverflow.com/a/713921/649497が、その答えの問題を克服し、それはあなたが空のコンストラクタとViewDataDictionaryをインスタンス化した場合のViewDataが行方不明になるということです。私は最初に、受け入れられたソリューションでこの問題を解決しましたが、私のValidationSummaryが部分ビューで機能しないことがわかりました。この解決策は私にとってそれを解決しました。この回答では、問題を解決し、部分ビューでViewDataを保持するために、より多くの認識が必要です。
BruceHill 2013

1
@Franc Pこれは実際にはViewBag値を失うことなく機能し、したがってnullモデルを渡しました。ありがとう。
Zaker、2015年

パーシャルでViewBagアクセスが必要な場合、これが正しい答えです!
Daniel Lorenz

12

解決策は、次のようなHtmlHelperを作成することです。

public static MvcHtmlString Partial<T>(this HtmlHelper htmlHelper, string partialViewName, T model)
{
    ViewDataDictionary viewData = new ViewDataDictionary(htmlHelper.ViewData)
    {
        Model = model
    };
    return PartialExtensions.Partial(htmlHelper, partialViewName, model, viewData);
}

Partial<T>(...)前にマッチしたPartial(...)ので、便利でコンパイルなし曖昧エラー。

個人的には動作を理解するのが難しいと思います-これをデザインの選択として想像するのは難しいようです?


1
これが最後にやったことです。asp.net mvcには、意味のある多くの設計上の選択/動作はありません。それを放棄して以来。他の人に役立つので、+ 1を持っている
Andrew Bullock

良いものですが、ユーザーには不明瞭です。私の同僚が彼のプロジェクトで使用するものに慣れているとしましょう。新しいものを始めます。次に、このオーバーロードと出来上がりを追加することを完全に忘れてください。十分にテストしていなかったため、本番環境で例外が発生し始めています。別の名前はbeter imhoです。
Jaap

11

これは答えられていますが、私はこれに遭遇し、私のプロジェクトでこの問題を回避するのではなく、この問題を解決したいと思いましたnew ViewDataDictionary()

拡張メソッドのセットを作成しました:https : //github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs
モデルがnullの場合、パーシャルを呼び出さないメソッドもいくつか追加しました、これはifステートメントの多くを節約します。

私はRazor用にそれらを作成しましたが、それらのいくつかはaspxスタイルのビューでも動作するはずです(HelperResultを使用するものはおそらく互換性がありません)。

拡張メソッドは次のようになります。

@* calls the partial with Model = null *@
@Html.PartialOrNull("PartialName", null)
@* does not call the partial if the model is null *@
@Html.PartialOrDiscard("PartialName", null)

IEnumerable<object>モデルにはメソッドもあり、破棄のものはRazorラムダで呼び出すこともできます。これにより、部分的な結果をいくつかのhtmlでラップできます。

よろしければ、お気軽にご利用ください。


1
MVC5の時点でもまだ有用です:6/25/2014。ありがとう。
Jason

1

これに対する私の回避策は:


<% Html.RenderPartial("TaskList", Model.Tasks ?? new List()); %>


これは汚い解決策です。部分ビューでは、リストに値があるかどうか、それがnullかどうかをチェックするのではなく、nullモデルをチェックできるはずです。
マッド2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.