从父对象向部分视图传递空的子对象

8

我有一个对象,其中包含我的ASP.NET MVC Web应用程序的模型。传递给视图的模型具有该特定视图上“小工具”的子模型。每个这些子模型都会传递到部分视图(小工具)。

问题在于当视图模型中有空模型时。请参见下面的示例。

视图模型:

public class FooBarHolder()
{
     public FooBar1 FooBar1 { get; set; }
     public FooBar2 FooBar2 { get; set; }
}

我们将FooBarHolder传递到视图中,在视图内部进行调用,例如:
<% Html.RenderPartial("Foo", Model.FooBar1); %>
<% Html.RenderPartial("Foo2", Model.FooBar2); %>

假设Model.FooBar2为空。从强类型的局部视图中,我看到的错误信息是:“此视图期望一个类型为FooBar2的模型,但得到了一个类型为FooBarHolder的模型。”

为什么会发生这种情况,而不是直接传入null?

3个回答

8

这就是RenderPartial方法的工作方式(我知道应该有文档记录、博客介绍等,但我也觉得这有点奇怪)。如果您没有指定模型或传递null,它将使用父页面的模型。为了避免这种情况,您可以使用空合并运算符:

<% Html.RenderPartial("Foo", Model.FooBar1 ?? new Foo()); %>

如果你真的很好奇这是如何实现的,以下是ASP.NET MVC 2源代码相关部分的摘录:

// Renders the partial view with an empty view data and the given model
public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model) {
    htmlHelper.RenderPartialInternal(partialViewName, htmlHelper.ViewData, model, htmlHelper.ViewContext.Writer, ViewEngines.Engines);
}

internal virtual void RenderPartialInternal(string partialViewName, ViewDataDictionary viewData, object model, TextWriter writer, ViewEngineCollection viewEngineCollection) {
    if (String.IsNullOrEmpty(partialViewName)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "partialViewName");
    }

    ViewDataDictionary newViewData = null;

    if (model == null) {
        if (viewData == null) {
            newViewData = new ViewDataDictionary(ViewData);
        }
        else {
            newViewData = new ViewDataDictionary(viewData);
        }
    }
    else {
        if (viewData == null) {
            newViewData = new ViewDataDictionary(model);
        }
        else {
            newViewData = new ViewDataDictionary(viewData) { Model = model };
        }
    }

    ViewContext newViewContext = new ViewContext(ViewContext, ViewContext.View, newViewData, ViewContext.TempData, writer);
    IView view = FindPartialView(newViewContext, partialViewName, viewEngineCollection);
    view.Render(newViewContext, writer);
}

注意如何处理空模型的情况。

感谢您提供这么清晰的解释,如果没有您,我可能会卡在那里几个小时!在您的情况下,您创建了一个新的Foo(),但是如果您真的想在那里传递null怎么办? - Michiel Cornille
子对象为空,因此它会恢复到父模型。感谢澄清。愿你的生活充满独角兽之吻和Care Bear的彩虹糖果腹泻。 - TSmith

2
为了避免在子模型为 null 时传递父模型,请使用以下技巧:
@Html.Partial("Child", null, new ViewDataDictionary<ChildType>(childInstance/*this can be null*/))

Credit where due...


1

我对于这个奇怪的“特性”(或者可能是bug?)的解决方法是:

<% Html.RenderPartial(
    "Foo2", 
    new ViewDataDictionary(ViewData) { Model = Model.FooBar2 }
); %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接