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 350 posts 1102 karma points MVP 8x 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 350 posts 1102 karma points MVP 8x 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 350 posts 1102 karma points MVP 8x 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.

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies