Copied to clipboard

Flag this post as spam?

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


  • Dennis Spijkerboer 53 posts 95 karma points
    Jun 16, 2014 @ 14:27
    Dennis Spijkerboer
    0

    Strongly typing in Umbraco 7.1.4

    After some sessions at Codegarden I tried to implement some stornlgy typing based on Stéphane's presentation.

    Oh, I am using umbraco 7.1.4

    I have a basic (very basic) class:

    public class TextPage: PublishedContentModel
    {
        public TextPage(IPublishedContent content) : base(content)
        {
        }
    
    }
    

    I have my main template:

      @foreach (var child in Model.Content.Children)
      {
         @Html.Partial("demoPartial", child)
      }
    

    And my partial view:

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<TextPage>
    <h1>@Model.Name</h1>
    

    I get the following error:

    Cannot cast source content type Umbraco.Web.PublishedCache.XmlPublishedCache.XmlPublishedContent to view model type Umbraco7Examples.Models.TextPage.
    

    I must be missing something.

  • Bruce 17 posts 82 karma points
    Jun 16, 2014 @ 15:33
    Bruce
    0

    Your main model on the page may be TextPage but when you scroll through Model.Content.Children the children aren't of type TextPage hence the casting error.

    i.e. "child" is not of type TextPage, it's Umbraco Published Content.

  • Dennis Spijkerboer 53 posts 95 karma points
    Jun 16, 2014 @ 15:37
    Dennis Spijkerboer
    0

    The childpages are all from the type TextPage (I know the code issn't failsafe, but it's just for demo purpose). Even with other doctypes there should not be a problem because there are no custom properties.

  • Bruce 17 posts 82 karma points
    Jun 16, 2014 @ 15:44
    Bruce
    0

    I've not seen this presentation but I've done a number of strongly typed Umbraco models so perhaps the presentation is using a different method to what I'm used to. However, from what I can see you aren't actually dealing with childpages of "TextPage" as you haven't casted them to that type. The error itself seems to back up that assumption as it's saying the source children are XMLPublishedContent and not TextPage (hence the error). You would probably need to do something like this:

    @foreach(var child inModel.Content.Children)
     
    {
         
    @Html.Partial("demoPartial", new TextPage(child))
     
    }

    For that to work.

  • Dallas 133 posts 405 karma points
    Jun 17, 2014 @ 04:28
    Dallas
    104

    Dennis

    After seeing Stéphane's presentation slide deck on twitter I also tried to implement a strongly typed model using the PublishedContentModel. I was getting the same error 

    Cannot cast source content type Umbraco.Web.PublishedCache.XmlPublishedCache.XmlPublishedContent to view model type ....

    My understanding is that to use the PublishedContentModel classes you need to use a IPublishedContentModelFactory (slide 42) but no factory is enabled by default. I was able to enable the builtin PublishedContentModelFactory by registering it in the ApplicationStarting event

    public class RegisterEvents : ApplicationEventHandler { 
    protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) {
    var types = PluginManager.Current.ResolveTypes();
    PublishedContentModelFactoryResolver.Current.SetFactory(new PublishedContentModelFactory(types)); 
    }

    If you get this error

    The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type ....

    you need to change the layout master pages to use UmbracoViewPage (not UmbracoTemplatePage)

  • Dennis Spijkerboer 53 posts 95 karma points
    Jun 17, 2014 @ 09:09
    Dennis Spijkerboer
    0

    Hi

    Thanks for your reply.I still run into the same issue, although I got the factory in place:

     public class AppStarting : ApplicationEventHandler
        {
    
            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication,
                ApplicationContext applicationContext)
            {
    
                var types = PluginManager.Current.ResolveTypes<PublishedContentModel>();
    
                PublishedContentModelFactoryResolver.Current.SetFactory(new PublishedContentModelFactory(types));
    
                base.ApplicationStarting(umbracoApplication, applicationContext);
            }
        }
    

    Checked with a breakpoint, the variable types contains my TextPage class. Changed all the UmbracoTemplatePage masterpages to UmbracoViewPage, that works fine.

    So I'm stuck with this error.

    Cannot cast source content type Umbraco.Web.PublishedCache.XmlPublishedCache.XmlPublishedContent to view model type Umbraco7Examples.Models.TextPage.
    
  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Jun 17, 2014 @ 09:11
    Dave Woestenborghs
    1

    Maybe a stupid question, but does you doctype has the alias "TextPage" ?

    Dave

  • Dennis Spijkerboer 53 posts 95 karma points
    Jun 17, 2014 @ 09:18
    Dennis Spijkerboer
    0

    H5IS!! It was umbTextPage..

    Thank you guys! The registering of the factory was the import bit so I Mark your answer as the solution.

    H5YR!

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Jun 17, 2014 @ 09:19
    Dave Woestenborghs
    0

    glad you sorted it out. Keep us posted on your findings !

    Dave

  • Zac 223 posts 575 karma points
    Nov 13, 2014 @ 14:27
    Zac
    0

    Hi guys,

    Thanks for this thread, it's very useful. Kudos to Dallas for his solution to register PublishedContentModelFactory

    Is there a way to implement PublishedContentModel without needing to explicitly define a partial class for each document type?

    What I'd ideally like is to be able to create a "BasePage" class that implements PublishedContentModel, and use a more specific class in other instances. E.g.

    public partial class BasePage : PublishedContentModel
    {
        public BasePage(IPublishedContent content) : base(content) { }
        public string PageTitle { get { return this.Content.GetPropertyValue<string>("pageTitle", this.Content.Name); } }
        //other common properties
    }
    

    It would be good to then use that class in your "TextPage" document, even though it has a different Alias. We could then create extensions for this base model, if and when we need them:

    public partial class StandardPage : BasePage
    {
        public StandardPage(IPublishedContent content) : base(content) { }
        public string SomethingMoreSpecific { get { return this.Content.GetPropertyValue<string>("somethingElse", this.Content.Name); } }
    }
    

    But it would be nice to be able to simply use BasePage for document types that don't really need their own class.

    Note: I am aware of Zbu.ModelsBuilder but I'm concerned about straying too far from the vanilla Umbraco 7 in fear of issues with future upgrades.

  • Zac 223 posts 575 karma points
    Nov 17, 2014 @ 12:11
    Zac
    0

    I've thought of another issue with the approach (as I understand it) from this thread and Stéphane's slideshow.

    Not only can you not inherit the BasePage PublishedContentModel (as you need to have the same Class name as your Doctype Alias), but you can't access any of this from the Layout page, since it will need to inherit from a more general PublishedContentModel class (such as my BasePage above) but this won't work.

    Obviously I'm missing something, I'm just not sure what. Is this where IPublishedContentModelFactory comes in, and some kind of manual configuration is required? I can't find any documentation at all for any of this besides the slideshow and what I can glean from this thread and Zbu.ModelsBuilder's brief explanations on the subject.

    Edit: So I also gave Zbu.ModelsBuilder a spin and it seemed to be doing pretty much the same thing - and I still can't use my strongly typed BasePage in the Master view anyway. Seems a little odd to go to all the trouble of strongly typing your views if you can't also use the properties in your Master pages.

    Edit 2: I can get at the properties in my Master view like this:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        var BaseContent = (BasePage)Model.Content;
    }
    <head>
        <title>@BaseContent.PageTitle</title>
    </head>
    <body>
        @RenderBody()
    </body>
    
Please Sign in or register to post replies

Write your reply to:

Draft