简体   繁体   English

将null子对象从父对象传递到局部视图

[英]Passing null child object from parent object to a partial view

I have an object which contains models for my ASP.NET MVC web app. 我有一个对象,其中包含我的ASP.NET MVC Web应用程序的模型。 The Model that is being passed into the view has sub models for "gadgets" on that particular view. 传递到视图中的模型具有该特定视图上“小工具”的子模型。 Each of these sub models gets passed to a partial view (gadget). 这些子模型中的每一个都被传递到局部视图(小工具)。

The problem is when I have a null model in the view model. 问题是我在视图模型中有一个空模型。 See example below. 见下面的例子。

View Model: 查看型号:

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

We pass FooBarHolder into the view and inside the view we make calls such as 我们将FooBarHolder传递到视图中,并在视图内部进行调用,例如

<% Html.RenderPartial("Foo", Model.FooBar1); %>
<% Html.RenderPartial("Foo2", Model.FooBar2); %>

Now say for instance that Model.FooBar2 was null. 现在说比较Model.FooBar2为null。 What I am experiencing from the strongly typed partial view is an error that says "This view expected a model of type FooBar2 but got a model of type FooBarHolder." 我从强类型的局部视图中遇到的是一个错误,上面写着“这个视图需要一个类型为FooBar2的模型,但却得到了一个类型为FooBarHolder的模型。”

Why is this happening instead of just passing in a null? 为什么会发生这种情况而不是只传入null?

That's how the RenderPartial method works (I know should have been documented, blogged about, etc..., me too I find this a little strange). 这就是RenderPartial方法的工作方式(我知道应该有记录,博客等等......我也觉得这有点奇怪)。 If you do not specify a model or pass null it will use the model of the parent page. 如果未指定模型或传递null ,则将使用父页面的模型。 To avoid this you might use the null coalescing operator: 为避免这种情况,您可以使用null合并运算符:

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

And if you are really curious as to how this is implemented there's an excerpt from the relevant parts of the ASP.NET MVC 2 source code: 如果您对如何实现它非常好奇,那么可以从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);
}

Notice how the case of null model is handled. 注意如何处理null模型的情况。

To avoid passing parent's model when child model is null, use this trick: 为避免在子模型为null时传递父模型,请使用此技巧:

@Html.Partial("Child", null, new ViewDataDictionary<ChildType>(childInstance/*this can be null*/))

Credit where due... 信用到期......

My workaround for this strange "feature" (or bug maybe?) is: 我对这个奇怪的“功能”(或可能是错误?)的解决方法是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM