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.
Не стесняйтесь использовать их, если хотите.