ASP.NET MVC, строго типизированные представления, параметры частичного просмотра сбой

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

System.Web.Mvc.ViewPage<Foo>

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

System.Web.Mvc.ViewUserControl<string>  

вот так:

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

Тогда почему он будет это делать:

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

когда бар не инициализируется?

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

Ответ 1

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

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

<% Html.RenderPartial( "_Bar", Model.Bar ?? string.Empty ) %>

Ответ 2

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

...

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

...

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

ОБНОВЛЕНО:

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

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

Ответ 3

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

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

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

Ответ 4

Хотя на это был дан ответ, я столкнулся с этим и решил, что хочу решить эту проблему для моего проекта, вместо того, чтобы обойти его с помощью "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, а отбрасываемые также можно вызвать с помощью лямбда Razor, которые позволяют обернуть частичный результат с помощью некоторого html.

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