Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Ault Nathanielsz 27 posts 121 karma points
    1 week ago
    Ault Nathanielsz
    0

    Layouts (master pages) and Models Builder

    Summary How can different doctypes use the same layout (cshtml file)?

    Setup V7.8. modelsbuilder is on using AppData

    DocTypes There are 3 component doctypes:

    • internalFields
    • externalFields
    • content

    These components are then used to build 3 composite doctypes:

    • webPage
    • blogSection
    • blogPost

    The only difference between webPage and blogSection is that the latter has "listing" turned on. A single added field is all that makes a blogPost different from a webPage.

    Templates Each doctype is linked to a corresponding template. They then call the same layout.

    Here is the start of the webPage template:

     @inherits Umbraco.Web.Mvc.UmbracoTemplatePage<ContentModels.WtWebPage> 
    @usingContentModels = Umbraco.Web.PublishedContentModels;  
    @{  
         Layout = "wtSiteLayout.cshtml"; 
     }
    

    The Issue How do I bind my layout to all three models? If I use the same technique as above, I can get it to work only if the model matches the template that calls it. But then it only works for the corresponding doctype. Any node using a different doctype results in a binding error:

    Cannot bind source content type Umbraco.Web.PublishedContentModels.BlogSection to model content type Umbraco.Web.PublishedContentModels.WebPage.

    I am sure that there is something basic that I am missing here. Any help would be appreciated.

  • David Peck 585 posts 1548 karma points c-trib
    1 week ago
    David Peck
    0

    I think the simple answer is that you can create a new interface (e.g. IBaseCompositePage and have that interface inherit from your three composite interfaces e.g.:

    using Umbraco.Web.PublishedContentModels;
    namespace YourNamespaceHere {
        public interface IBaseCompositePage : IInternalFields, IExternalFields, IContent
        { }
    }
    

    Then you can have your view as:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage<YourNamespaceHere.IBaseCompositePage> 
    @using ContentModels = Umbraco.Web.PublishedContentModels;  
    @{  
         Layout = "wtSiteLayout.cshtml"; 
     }
    

    You'll still need to check the type of your model to get the field added to blogPost in a strongly typed way, but then again you could just us @Model.GetPropertyValue("myExtraProperty").

    Two words of caution.

    1. Having such a huge quantity of shared properties sounds like a bit of an anti-pattern if they aren't actually relevant to every page type.
    2. I wonder if it might not be better sticking with your page model just being an IPublishedContent, and then use partials for each section of your page. Those are probably more likely to be compatible with passing in a model of just one of your composite interfaces.
  • Ault Nathanielsz 27 posts 121 karma points
    5 days ago
    Ault Nathanielsz
    0

    Thanks for the reply. I have been reading up on the models builder and how to use it. But a follow-on questions to your answer: Is this interface the only place I declare my namespace (alluded to by YourNamespaceHere in your reply)?

    I have looked through the automatically generated classes and interfaces, and they all set their namespace as Umbraco.Web.PublishedContentModels. Why would I not just add my interface to that namespace?

    (I ask out of complete ignorance, not because I am puzzled by your answer.)

  • David Peck 585 posts 1548 karma points c-trib
    5 days ago
    David Peck
    0

    If you're create your own interface, then you can namespace it anywhere you like. But where you use the interface you'll need to include that namespace, as per any interface... I apologise if I misunderstand.

    You can absolutely put your interface in Umbraco.Web.PublishedContentModels if you like.

  • Ault Nathanielsz 27 posts 121 karma points
    4 days ago
    Ault Nathanielsz
    0

    Thanks David, that makes perfect sense.

    Only problem is, I now get an error message about binding...

    Cannot bind source content type Umbraco.Web.PublishedContentModels.WtWebPage to model content type Umbraco.Web.PublishedContentModels.IwtComposite

    Any thoughts on how to handle this?

  • David Peck 585 posts 1548 karma points c-trib
    4 days ago
    David Peck
    0

    That suggests that WtWebPage doesn't implement IWtComposite. Assuming both classes are generated by the models builder, do check that the composite has been correctly assigned and the models are up to date.

Please Sign in or register to post replies

Write your reply to:

Draft