Полиморфизм строго типизированных мастер-страниц - вложенные мастер-страницы игнорируют атрибут наследования - PullRequest
1 голос
/ 30 мая 2009

Я сейчас создаю систему CMS и обнаружил, что следующее не работает.

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

Трудно объяснить, поэтому я позволю своему коду (без большого количества пуха) говорить ... надеюсь, это имеет смысл!

РЕДАКТИРОВАТЬ: Кажется, что компилятор полностью игнорирует атрибут «наследует» второй главной страницы - см. В нижней части вопроса.

ContentViewData.cs - обратите внимание, что он наследуется от BaseViewData

public class ContentViewData : BaseViewData
{
    public MyCMS.Data.Models.Content ContentItem { get; set; }
}

Site.Master - Обратите внимание на строго типизированные данные представления типа BaseViewData

<%@ Master
    Language="C#"
    Inherits="System.Web.Mvc.ViewMasterPage<MyCMS.WebSite.ViewData.BaseViewData>" %>

Content.Master - Обратите внимание на строго типизированные данные представления типа ContentViewData и тот факт, что это дочерняя главная страница Site.Master

<%@ Master
    Language="C#"
    MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewMasterPage<MyCMS.WebSite.ViewData.ContentViewData>" %>

...blah blah blah...

<% Html.RenderPartial("ContentItemImage", Model.ContentItem); %>

ContentItemImage.ascx

<%@ Control
    Language="C#"
    Inherits="System.Web.Mvc.ViewUserControl<MyCMS.Data.Models.Content>" %>

<% if (Model.HasPrimaryPhoto)
   { %>
    <img src="/content/photos/<%= Model.GetPrimaryPhoto.ThumbFileName %>"
         title="<%= Model.GetPrimaryPhoto.Caption %>" />
<% } %>

Теперь внутри Content.Master, если я попытаюсь визуализировать ContentItemImage частичным и сослаться на свойство объекта ContentViewData (в частности, свойство 'ContentItem'), как я это повторил ниже.

<% Html.RenderPartial("ContentItemImage", Model.ContentItem); %>

Если падает в этой строке со следующей ошибкой

Ошибка компиляции

CS1061: «объект» не содержит определения «ContentItem» и нет метод расширения 'ContentItem' принимая первый аргумент типа «объект» может быть найден (вы отсутствует директива использования или ссылка на сборку?)

НО, если я что-то поменяю, все будет нормально и здорово.

Content.Master - Обратите внимание, что я передаю в RenderPartial () всю модель (объект ContentViewData), а не пытаюсь сослаться на свойство объекта ContentViewData

<%@ Master
    Language="C#"
    MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewMasterPage<MyCMS.WebSite.ViewData.ContentViewData>" %>

...blah blah blah...

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

ContentItemImage.ascx - обратите внимание на изменение строго типизированных данных представления из MyCMS.Data.Models.Content в классе ContentViewData.

<%@ Control
    Language="C#"
    Inherits="System.Web.Mvc.ViewUserControl<MyCMS.WebSite.ViewData.ContentViewData>" %>

<% if (Model.ContentItem.HasPrimaryPhoto)
   { %>
    <img src="/content/photos/<%= Model.ContentItem.GetPrimaryPhoto.ThumbFileName %>"
         title="<%= Model.ContentItem.GetPrimaryPhoto.Caption %>" />
<% } %>

Так что да, это работает, но это не алиби.

Заранее спасибо, Чарльз.

РЕДАКТИРОВАТЬ: Интересно, что компилятор полностью игнорирует атрибут «наследует» второй главной страницы.

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

<%@ Master
    Language="C#"
    MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewMasterPage<ThisDoesntExist.AtAll>" %>

Ответы [ 3 ]

1 голос
/ 30 мая 2009

Интересно ... Резонным предположением может быть то, что ваш объект ContentViewData передается в BaseViewData из-за некоторого взаимодействия с вашей вложенной главной страницей (если это действительно так, кому-то еще нужно будет выяснить, почему).

Вы можете проверить это:

<% Html.RenderPartial("ContentItemImage", ((MyCMS.WebSite.ViewData.ContentViewData)Model).ContentItem); %>

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

0 голосов
/ 16 ноября 2009

Просто попробуйте сделать следующее:

<%@ Master
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewMasterPage<MyCMS.WebSite.ViewData.ContentViewData>" %>

...blah blah blah...

<%= string.Empty %>

...blah blah blah...

<% Html.RenderPartial("ContentItemImage", Model.ContentItem); %>

Не спрашивайте ничего, просто попытайтесь вставить <% = string.Empty%> в код вашей главной страницы, а затем используйте строго типизированное свойство Model .

0 голосов
/ 01 июня 2009

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

Это наводит меня на мысль, что вложенная мастер-страница в ASP.NET MVC всегда будет наследовать от родительской мастер-страницы, и, как я видел, полностью игнорировать атрибут наследования.

РЕДАКТИРОВАТЬ: Здесь должно быть какое-то волшебство ... Если я уберу атрибут 'наследует', он не скомпилируется, потому что не знает о классе HtmlHelper. Но если у меня есть атрибут «наследует» с мусором, он компилируется.

Не работает

<%@ Master
    Language="C#"
    MasterPageFile="~/Views/Shared/Site.Master" %>

Работает ли

<%@ Master
    Language="C#"
    MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="Sysasfdaasdtem.Web.Mvsdfc.ViewMasterPage<ThisDoesntExist.AtAll>" %>

Очень странно.

...