Strongly typed master pages polymorphism - nested masterpages ignore inherit attribute

☆樱花仙子☆ 提交于 2019-12-11 07:47:54

问题


I'm currently creating a CMS system and found that the following doesn't work.

I do have a work around that isn't exactly ideal and feels dirty. I'm cool with it for now and not really that interested in a different approach (but don't let that stop you answering). What I am after is some kind of explaination on why it doesn't work - is it a bug in ASP.NET MVC?

It's hard to explain so I'll let my code (minus alot of fluff) do the talking... hope it makes sense!

EDIT: It seems that the compiler totally ignores the second masterpage's 'inherits' attribute - see at the bottom of the question.

ContentViewData.cs - notice it inherits from BaseViewData

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

Site.Master - Notice the strongly typed viewdata of type BaseViewData

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

Content.Master - Notice the strongly typed viewdata of type ContentViewData and the fact that it's a child masterpage of 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 %>" />
<% } %>

Now inside the Content.Master if I try and render the ContentItemImage partial and refer to a property on the ContentViewData object (specifically the 'ContentItem' property) like I have - repeated below.

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

If falls over on that line with the following error

Compilation Error

CS1061: 'object' does not contain a definition for 'ContentItem' and no extension method 'ContentItem' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

BUT if I change things up like so, it all works fine and dandy.

Content.Master - Notice I'm passing into RenderPartial() the whole Model (ContentViewData object) rather than trying to refer to a property on the ContentViewData object

<%@ 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 - notice the changed strongly typed viewdata from MyCMS.Data.Models.Content to the ContentViewData class.

<%@ 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 %>" />
<% } %>

So yeah, that works but it aint go not alibi.

Thanks in advance, Charles.

EDIT: Interestingly it seems that the compiler totally ignores the second master page's 'inherits' attribute.

Eg. I can do this and it still compiles without a complaint...

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

回答1:


Interesting...A resonable guess would be that your ContentViewData object is being upcast to BaseViewData due to some interaction with your nested master page (if that is indeed the case, someone else will need to weigh in as to why).

You could verify trying this:

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

The reason your workaround "works" is because your partial view is typed for ContentViewData, so when you pass in Model it is downcast to that type.




回答2:


As you can see from my edit, it seems that the compiler totally ignores the nested master page's 'inherits' attribute.

This leads me to believe that a nested masterpage in ASP.NET MVC will always inherit from it's parent masterpage and as I've witnessed, totally ignore the inherits attribute.

EDIT: There must be some magic going on here... If I remove the 'inherits' attribute it won't compile because it doesn't know about the HtmlHelper class. But if I have the 'inherits' attribute in there with garbage inside it, it does compile.

Doesn't work

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

Does work

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

Very odd indeed.




回答3:


Just try to do the next thing:

<%@ 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); %>

Don't ask anything, just try to put <%= string.Empty %> in your master page's code and then use your strongly typed Model property.



来源:https://stackoverflow.com/questions/928911/strongly-typed-master-pages-polymorphism-nested-masterpages-ignore-inherit-att

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!