Copied to clipboard

Flag this post as spam?

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


  • Daniël Knippers 90 posts 567 karma points MVP c-trib
    May 22, 2017 @ 11:03
    Daniël Knippers
    0

    Route Hijacking + DTGE Preview mode issues

    Hi,

    Thank you for this great package! We are experimenting a bit with it at Perplex and I'm running into an issue with the Preview mode (i.e. the rendering in Umbraco) in combination with custom view models.

    We almost always create custom controllers for every Doctype so we can use a custom model for the view which contains any logic, rather than having all this logic in the view itself. In order to do that, we hijack the Umbraco routes to inject our view model. For example, our Home controller will generally look something like this:

    public class HomeController : SurfaceController, IRenderController
    {
        public ActionResult Index()
        {
            return View("Home", new HomeViewModel());
        }
    }
    

    This raises an exception in App_Plugins\DoctypeGridEditor\Render\DocTypeGridEditorPreviewer.cshtml:

    Cannot bind source type DTGE_Test.Models.Views.HomeViewModel to model type Umbraco.Core.Models.IPublishedContent.
    

    I understand why this is happening, considering the Preview mode is basically "hijacking" the Index method of our Home controller (when the Grid property is on that doctype) to render its preview, and only changes the .ViewName property to the DTGEPreviewer.cshtml but not the Model (which is read-only). In the DocTypeGridEditorPreviewer the following line is at the top:

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<IPublishedContent>
    

    In our case, we pass in a custom model which does not directly bind to IPublishedContent hence it fails. Since you do not actually use the Model in that view, a simple fix would be to change it to something like this:

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<object>
    

    In that case it will work with default Umbraco (where the model is a RenderModel) and with custom viewmodels. I don't think this breaks anything.

    Please let me know what you think about that change and if there is another way to do this. It's totally possible I was doing it wrong to begin with.

    I am also using a custom DocTypeGridEditorSurfaceController for the grid editor itself, but this does not seem to influence the outcome. I also get the error without this (i.e., when DTGE simply renders views/partials/[doctypeAlias].cshtml)

    Kind regards,

    Daniël

  • Dave Woestenborghs 3214 posts 10806 karma points MVP 4x admin c-trib
    May 22, 2017 @ 11:25
    Dave Woestenborghs
    0

    Hi Daniël,

    We are also using DTGE in combination with Models builder and Route Hijacking. We don't experience the issue that you are describing.

    I think the problem occcurs because you are doing the route hijacking with a surface controller. We had some issues in the past with that as well.

    According to Shannon in this post this should not be done : https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/73791-getting-an-error-with-custom-routes-could-not-find-a-surface-controller-route-in-the-routetable-for-controller-name-authorization#comment-236516

    Dave

  • Daniël Knippers 90 posts 567 karma points MVP c-trib
    May 22, 2017 @ 11:35
    Daniël Knippers
    0

    Hi Dave,

    Thank you for your quick reply and suggestion. I just tried the regular way of route-hijacking (as far as I know), but this results in a similar issue.

    That is, if I use the following definition of HomeController the exact same exception is raised:

    public class HomeController : RenderMvcController
    {
        public override ActionResult Index(RenderModel m)
        {
            return CurrentTemplate(new HomeViewModel());
        }
    }
    

    Could you perhaps show an example of on of your controllers with some custom view model so I can see if it works here? Thanks!

    Daniël

  • Dave Woestenborghs 3214 posts 10806 karma points MVP 4x admin c-trib
    May 22, 2017 @ 11:45
    Dave Woestenborghs
    0

    Hi Daniël,

    How does you HomeViewModel look ? I haven't used custom models in my templates before ? Can a master view handle this, because I think you will have different viewmodels per content type?

    Dave

  • Daniël Knippers 90 posts 567 karma points MVP c-trib
    May 22, 2017 @ 11:52
    Daniël Knippers
    0

    Hi Dave,

    It appears that if the custom View Model implements the IRenderModel interface it will work, as Umbraco appears to work some magic in that case and pass the IPublishedContent properly to the preview View.

    That is, when the View Model is specified like below it will work, and in our case the View Models indeed include the IPublishedContent so implementation is trivial, but I still think it would be nice if this would work with any View Model, not requiring them to implement IRenderModel.

    public class HomeViewModel : IRenderModel
    {
        // We have this one available through a generic base class, 
        // put directly here for simplicity
        public Home Content { get; }
    
        // Explicitly implement IRenderModel here.
        IPublishedContent IRenderModel.Content => Content;
    }
    

    I suppose if it works for your custom view models, those also implement IRenderModel (or perhaps IPublishedContent?). Otherwise I would expect a similar exception to be raised.

    Daniël

  • Dave Woestenborghs 3214 posts 10806 karma points MVP 4x admin c-trib
    May 22, 2017 @ 11:56
    Dave Woestenborghs
    1

    Hi Daniël,

    We use the models generated by models builder (some times extended with custom code) in our templates. And these models implement IPublishedContent.

    Dave

  • Daniël Knippers 90 posts 567 karma points MVP c-trib
    May 22, 2017 @ 12:02
    Daniël Knippers
    0

    Hi Dave,

    Ah exactly, that makes sense that those issues would not arise in that case. We are also thinking about perhaps just extending ModelsBuilder classes and use those as our View Models instead of creating view models that wrap a ModelsBuilder model, but there's some discussion as to whether that's always desirable. For example, if we want to render 2 totally different templates for the same Models Builder class, we may want to have 2 view models with different logic, but both containing that 1 models builder class with all Umbraco data. Anyway, that's a different topic :)

    Thanks for your input on this topic! I do believe making DTGE work for regular view models (i.e., not requiring them to implement IRenderModel / IPublishedContent) would be nice, but let's see what the authors think about this.

    Daniël

Please Sign in or register to post replies

Write your reply to:

Draft