renderpartial с нулевой моделью получает неправильный тип - PullRequest
192 голосов
/ 16 марта 2009

У меня есть страница:

<%@ Page Inherits="System.Web.Mvc.View<DTOSearchResults>" %>

И на нем следующее:

<% Html.RenderPartial("TaskList", Model.Tasks); %>

Вот объект DTO:

public class DTOSearchResults
{
    public string SearchTerm { get; set; }
    public IEnumerable<Task> Tasks { get; set; }

и вот частичное:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Task>>" %>

Когда Model.Tasks не имеет значение null, все работает нормально. Однако, когда его ноль, я получаю:

Элемент модели, переданный в словарь, имеет тип 'DTOSearchResults', но для этого словаря требуется элемент модели типа 'System.Collections.Generic.IEnumerable`1 [Задача].

Я подумал, что он не должен знать, какую перегрузку использовать, поэтому я сделал это (см. Ниже), чтобы быть явным, но я все еще получаю ту же проблему!

<% Html.RenderPartial("TaskList", (object)Model.Tasks, null); %>

Я знаю, что могу обойти это, проверяя на ноль или даже не передавая ноль, но это не главное. Почему это происходит?

Ответы [ 7 ]

339 голосов
/ 03 апреля 2009

Эндрю Я думаю, что проблема, которую вы получаете, является результатом метода RenderPartial, использующего модель вызова (представления) для частичного представления, когда модель, которую вы передаете, является нулевой.

<% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary()); %>

Это помогает?

45 голосов
/ 15 марта 2011

@ myandmycode ответ хороший, но чуть короче будет

<% Html.RenderPartial("TaskList", new ViewDataDictionary(Model.Tasks)); %>

Это работает, потому что ViewDataDictionary - это то, что содержит модель, и она может принять модель в качестве параметра конструктора. Это в основном передает «полный» словарь данных представления, который, конечно, содержит только модель с нулевым значением.

24 голосов
/ 30 июля 2010

Похоже, что когда свойство модели, которую вы передаете, равно нулю, MVC преднамеренно возвращается к «родительской» модели. По-видимому, механизм MVC интерпретирует нулевое значение модели как намерение использовать предыдущее.

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

19 голосов
/ 20 августа 2012

Если вы не хотите потерять свои предыдущие ViewData в частичном представлении, вы можете попробовать:

<% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary(ViewData){Model = null});%>
11 голосов
/ 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<object> моделей, а отбрасываемые также можно вызывать с помощью лямбды Razor, которые позволяют обернуть частичный результат некоторым HTML-кодом.

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

11 голосов
/ 29 ноября 2011

Решением было бы создать HtmlHelper следующим образом:

public static MvcHtmlString Partial<T>(this HtmlHelper htmlHelper, string partialViewName, T model)
{
    ViewDataDictionary viewData = new ViewDataDictionary(htmlHelper.ViewData)
    {
        Model = model
    };
    return PartialExtensions.Partial(htmlHelper, partialViewName, model, viewData);
}

Partial<T>(...) сопоставляется раньше, чем Partial(...), что очень удобно и нет ошибки неоднозначности при компиляции.

Лично мне трудно понять поведение - кажется, трудно представить это как выбор дизайна?

0 голосов
/ 21 января 2015

Мой обходной путь:


<% Html.RenderPartial("TaskList", Model.Tasks ?? new List()); %>

...