Copied to clipboard

Flag this post as spam?

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


  • Sotiris Filippidis 286 posts 1501 karma points
    Jul 02, 2016 @ 12:08
    Sotiris Filippidis
    0

    Route Hijacking and Models Builder - how?

    My question is based on this post by Sebastian Jaansen, written in 2014: https://umbraco.com/follow-us/blog-archive/2014/1/27/a-practical-example-of-route-hijacking-in-umbraco/

    I found this example of using route hijacking pretty tempting, so I started trying to create my own. The only difference is that I'm using strongly-typed models (through the now-core ModelsBuilder), and I can't find a way to make my custom model inherit the properties of the "normal" model as Sebastian does with his own.

    In the example, Sebastian is creating a model in the following way so that he can take advantage of the document type's existing properties, essentially adding his own custom properties on top:

     public class BlogOverview : RenderModel
        {
            public BlogOverview(IPublishedContent content) : base(content)
            { }
    
            public int Page { get; set; }
    
            // More custom properties
        }
    

    My own model is called BlogListModel, while my strongly-typed class that I would use instead of a generic IPublishedContent is PageBlogList (essentially, the name of the underlying document type). So what I need is a BlogListModel that will extend PageBlogList with more custom properties.

    So my own model starts with something like this:

    public class BlogListModel : RenderModel<PageBlogList> {
            public BlogListModel(PageBlogList content) : base(content) { 
                  // Some code here ....
            }
    }
    

    But, of course, this returns a model that is an IPublishedContent and has the additional properties defined, but not the strongly-typed properties of PageBlogList.

    In addition, to even use this from my controller, I had to do something like this merry-go-round:

    BlogListModel currPage = new BlogListModel ((PageBlogList)model.Content);
    

    Regardless, the problem remains: My currPage is essentially an IPublishedContent, not a PageBlogList. So I can't use extensions built for this, or even its strongly-typed properties.

    I don't know if I'm making any sense, but I believe I've totally missed something in the process. Could anybody enlighten me on how (and if) I can correctly use route hijacking with strongly-typed PublishedContentModels?

  • Micha Somers 134 posts 597 karma points
    Jul 02, 2016 @ 14:57
    Micha Somers
    0

    Hi Sotiris,

    Although the approach is a bit different, it maybe worthwhile looking at the source code of the hybrid framework:

    https://our.umbraco.org/projects/developer-tools/hybrid-framework-for-umbraco-v7

    Although not really simple, the code related to MasterModel and SurfaceRenderMvcController might help you further.

  • Lars-Erik Aabech 349 posts 1100 karma points MVP 7x c-trib
    Jul 02, 2016 @ 15:34
    Lars-Erik Aabech
    0

    These two articles should help. Basically you should add your stuff to a partial instead of deriving.

    https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Understand-And-Extend

    https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Umbraco.ModelsBuilder

    Use dll mode.

    If you need custom routes, you might wanna go with a custom contentfinder and urlprovider.

    Playing at a children's park atm. Soz for short reply. Hth.

  • Sotiris Filippidis 286 posts 1501 karma points
    Jul 05, 2016 @ 09:28
    Sotiris Filippidis
    0

    I'm already in the process of reading the articles, thanks.

    My impression on Umbraco route hijacking was exactly that when I first heard about it: Custom routes. But I understood later that it actually had nothing to do with custom routes - it was just a way of intercepting Umbraco's default controller and adding code to make your views "dumber" (as they probably should be). So, as far as I can understand, what you're suggesting probably applies to a different context (e.g. true custom routes)?

  • Stephen 767 posts 2273 karma points c-trib
    Jul 04, 2016 @ 09:47
    Stephen
    0

    Could you copy your controller's method too? Not all the details, just the signature I guess + how you use the models. And also, an example of how you would want to use the models?

  • Sotiris Filippidis 286 posts 1501 karma points
    Jul 05, 2016 @ 09:25
    Sotiris Filippidis
    0
       public class PageBlogListController : Umbraco.Web.Mvc.RenderMvcController
        {
    
            public override ActionResult Index(RenderModel model)
            {
                BlogListModel currPage = new BlogListModel((PageBlogList)model.Content);
    
    //Some other stuff here
    
    
                return base.Index(model);
            }
        }
    

    This is a sample of what I've tried to do. This controller is supposed to create a BlogListModel (essentially, a PageBlogList with some more properties). I know this is not exactly the same as Sebastian's example, since I'm not going for CurrentTemplate but I was just trying to see whether the whole thing would work with stongly-typed models (which it didn't).

    I still believe that there's something I'm missing and it probably is silly, but can't figure out what.

  • Stephen 767 posts 2273 karma points c-trib
    Jul 05, 2016 @ 09:30
    Stephen
    100

    IIRC in 7.4.3 you can do eg

    public override ActionResult Index(PageBlogList model)
    {
        var viewModel = new BlogListModel(model);
        // stuff...
        return CurrentTemplate(viewModel);
    }
    

    Things to understand: if you use you own model you have to use CurrentTemplate, you cannot use base.Index(). Then, your custom model cannot add properties to PageBlogList, it just can encapsulate it.

    Making sense?

  • Lars-Erik Aabech 349 posts 1100 karma points MVP 7x c-trib
    Jul 05, 2016 @ 09:34
    Lars-Erik Aabech
    0

    Sweet. Didn't notice the RendereModel-less overload yet. :)

  • Sotiris Filippidis 286 posts 1501 karma points
    Jul 05, 2016 @ 14:49
    Sotiris Filippidis
    1

    Okay! It looks like that's what I was missing!

    So code looks like this now:

    Model (changed it to PageBlogListViewModel for more clarity):

        public partial class PageBlogListViewModel : PageBlogList
        {
            //Due to exception "Type DotSee.Models.BlogListModel is missing a public constructor with one argument of type IPublishedContent."
            public PageBlogListViewModel(IPublishedContent currPage) : base(currPage) { }
            public PageBlogListViewModel(PageBlogList currPage) : base(currPage) { }
            public int Page { get; set; }
    
            public int TotalPages { get; set; }
    
            public int TotalItems { get; set; }
    
           // Some more properties
        }
    }
    

    Controller:

    public class PageBlogListController : Umbraco.Web.Mvc.RenderMvcController
    {
    
        public ActionResult PageBlogList(PageBlogList model)
        {
            PageBlogListViewModel currPage = new PageBlogListViewModel(model);
    
            //more code here
    
    
            return CurrentTemplate(currPage);
        }
    }
    

    View:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage<PageBlogListViewModel>
    

    And now my view "knows" the add on properties that PageBlogListViewModel added to PageBlogList!

    It looks like it was a silly confusion after all. It's good to know that I can do hijacking on top of PublishedContentModels. Thanks for the help!

  • Lars-Erik Aabech 349 posts 1100 karma points MVP 7x c-trib
    Jul 05, 2016 @ 09:32
    Lars-Erik Aabech
    0

    If you've enabled ModelsBuilder in DLL mode, you should have a class under App_Data/Models.

    Make sure you include the models in your VS project. You can then type the RenderModel to that type.

    public override ActionResult Index(RenderModel<PageBlogList> model)
    

    There's no real need to adapt it to a BlogListModel if there's no new logic.
    In your view, you can now inherit UmbracoTemplatePage

    @inherits UmbracoTemplatePage<PageBlogList>
    <div>@Model.Content.TypedPropertyOnPageBlogList</div>
    

    If you do want extra logic, you can add a PageBlogList.partial.cs beside the PageBlogList.generated.cs file, and add methods and properties there.

Please Sign in or register to post replies

Write your reply to:

Draft