ASP.NET MVC, строго типизированные представления, сбой параметров частичного представления - PullRequest
22 голосов
/ 26 июня 2009

Если я получил представление, которое наследуется от:

System.Web.Mvc.ViewPage<Foo>

Где Foo имеет свойство Bar со строкой типа
И view хочет визуализировать строго типизированное частичное представление, которое наследуется от:

System.Web.Mvc.ViewUserControl<string>  

как это:

Html.RenderPartial("_Bar", Model.Bar);%>

Тогда, почему это бросит это:

Элемент модели, переданный в словарь, имеет тип 'Foo'
но для этого словаря требуется элемент модели типа 'System.String'.

когда бар не инициализирован?

Более конкретно: почему он пропускает Foo, где он должен пропускать ноль?

Ответы [ 4 ]

35 голосов
/ 26 июня 2009

Как указывает @Dennis, если значение модели равно нулю, оно будет использовать существующую модель из вида. Причина этого заключается в поддержке возможности вызова частичного представления с использованием подписи, содержащей только частичное имя представления, и повторного использования существующей модели. Внутри все помощники RenderPartial откладываются до одного метода RenderPartialInternal. Вы можете использовать этот метод для повторного использования существующей модели, передав нулевое значение для модели (что делает сигнатура, которая принимает только имя представления). Когда вы передаете нулевое значение в сигнатуру, содержащую как имя представления, так и объект модели, вы по существу копируете поведение метода, который принимает только имя представления.

Это должно исправить вашу проблему:

<% Html.RenderPartial( "_Bar", Model.Bar ?? string.Empty ) %>
9 голосов
/ 26 июня 2009

Посмотрите на источник ASP.NET MVC (HtmlHelper.cs -> метод RenderPartialInternal -> строка 258):

...

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

...

это именно ваш случай. ASP.NET MVC использует ViewData из вашего ViewContext

ОБНОВЛЕНИЕ:

Попробуйте вместо этого:

<% Html.RenderPartial("_Bar", Model.Bar ?? "Default" ); %>
4 голосов
/ 21 апреля 2012

Хотя на этот вопрос уже получен ответ, я наткнулся на это и решил, что хочу решить эту проблему для своего проекта, а не обходить его с помощью 'new ViewDataDictionary ()'.

Я создал набор методов расширения: https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs
Я также добавил несколько методов, которые не вызывают частичное, если модель нулевая, это сэкономит много операторов 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 моделей, а отбрасываемые также можно вызывать с помощью лямбды Razor, которые позволяют обернуть частичный результат некоторым HTML-кодом.

Не стесняйтесь использовать их, если хотите.

4 голосов
/ 26 июня 2009

Если вы передадите null в качестве модели в RenderPartial, то он будет смотреть на исходную модель, поэтому ошибка говорит foo.

Вы должны будете убедиться, что строка инициализирована как пустая строка вместо нуля.

Редактировать: @Arnis, посмотрите на исходный код. Это не ложь. Вы передаете null перегрузке RenderPartial. Вы не передаете Foo . Внутренне, система использует Модель из ViewContext вашей страницы (который является Foo ), когда вы передаете ноль Bar в RenderPartial.

...