2010-03-17 4 views
6

У меня есть объект, который содержит модели для моего веб-приложения ASP.NET MVC. Модель, которая передается в представление, имеет вспомогательные модели для «гаджетов» на этом конкретном представлении. Каждая из этих подмодулей передается в частичный вид (гаджет).Передача пустого дочернего объекта из родительского объекта в частичный вид

Проблема в том, что у меня есть нулевая модель в модели представления. См. Пример ниже.

вид Модель:

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».

Почему это происходит вместо того, чтобы просто пропустить нуль?

ответ

7

Вот как работает метод RenderPartial (я должен был документироваться, вести блог и т. Д.), Мне тоже это немного странно). Если вы не укажете модель или не пройдете null, она будет использовать модель родительской страницы. Чтобы избежать этого, вы можете использовать оператор нулевой коалесцирующий:

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

И если вы действительно любопытно, как это реализовано есть выдержка из соответствующих частей 2 исходного кода ASP.NET MVC:

// 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); 
} 

Обратите внимание, как обрабатывается случай с нулевой моделью.

+0

спасибо за это четкое объяснение, застряли бы в течение нескольких часов, если бы не для вас! В вашем случае вы создаете новый Foo() жесткий, что, если вы ДЕЙСТВИТЕЛЬНО хотите передать null там? –

1

Мой обходной путь для этого странного "особенности" (или ошибки может быть?) Является:

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

Вы протестировали это? Это не работает для строго типизированных просмотров здесь ... –

2

Чтобы избежать передач модели родителя, когда ребенок модель имеет нулевое значение, используйте этот трюк:

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

Credit where due...

Смежные вопросы