web-dev-qa-db-ja.com

nullモデルのrenderpartialに間違った型が渡される

私はページを持っています:

<%@ 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でない場合、すべてが正常に機能します。しかし、そのヌルが私が得るとき:

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

どのオーバーロードを使用するかを知らないはずだと思ったので、明示的にするためにこれを行いました(以下を参照)が、それでも同じ問題が発生します!

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

Nullをチェックするか、nullを渡さなくてもこの問題を回避できることはわかっていますが、それはポイントではありません。なぜこうなった?

192
Andrew Bullock

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

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

それは役立ちますか?

340
meandmycode

@myandmycodeの答えは良いですが、少し短いものは

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

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

45
configurator

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

ここで少し詳しく: ASP.NET MVC、厳密に型指定されたビュー、部分的なビューパラメーターグリッチ

24
Zack

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

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

解決策は、次のような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(...)の前に一致するため、コンパイル時に非常に便利で、あいまいさのエラーがありません。

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

11
Colin Breame

これは回答されましたが、私はこれに出くわし、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>モデル用のメソッドもあります。また、一部の結果をHTMLでラップできるようにするRazorラムダを使用して、破棄モデルを呼び出すこともできます。

必要に応じて自由に使用してください。

11
Jaap

これに対する私の回避策は次のとおりです。


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