Copied to clipboard

Flag this post as spam?

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


  • Nadia 45 posts 122 karma points
    May 04, 2020 @ 04:04
    Nadia
    0

    Custom Route Error in Umbraco 8 - No physical template file was found for template

    Hey,

    I am wanting to create a custom route, to pass through parameters to a page in a freindly url, rather than on a query string. Followed the instructions for creating a route, but didn't find it very clear, and am missing something.

    I am getting a "No physical template file was found for template " error. On inspecting the model it all looks good.

    My Custom Route code

      public class RegisterCustomRouteComposer : ComponentComposer<RegisterCustomRouteComponent>
        { }
    
        public class RegisterCustomRouteComponent : IComponent
        {
            public void Initialize()
            {
                // Custom route for explore search results
                // IPublishedContent for the current rendering page
                RouteTable.Routes.MapUmbracoRoute("AccomodationCustomRoute", "explore/accommodation/{region}/{type}/search", new
                {
                    controller = "AccommodationSearchResultsPage",
                    Action = "Search",
                    type = UrlParameter.Optional
                }, new AccomodationRouteHandler(17070));
            }
    
            public void Terminate()
            {
                // Nothing to terminate
            }
        }
    
        public class AccomodationRouteHandler: UmbracoVirtualNodeByIdRouteHandler 
        {
            public AccomodationRouteHandler(int realNodeId) : base(realNodeId)
            {
    
            }
        }
    

    And the Controller...

    public class AccommodationSearchResultsPageController : RenderMvcController
    {
    
        public  ActionResult Index(ContentModel model)
        {
    
            return base.Index(model);
        }
    
        public  ActionResult Search(ContentModel model, string type, string region)
        {
            AccommodationSearchResultsPage page = new AccommodationSearchResultsPage(model.Content)
            {
                Region = region, Type = type
            };
    
    
            return base.CurrentTemplate(model.Content);
        }
    }
    
  • Marc Goodson 2155 posts 14408 karma points MVP 9x c-trib
    May 04, 2020 @ 10:36
    Marc Goodson
    0

    Hi Nadia

    Is your Custom RenderMVCController actions hit? if you set a breakpoint inside the Index and Search Actions.. which one is hit by a request to your custom route?

    The id of the PublishedContent associated with the route: 17070 - does that correspond to a node with a template?

    and do you have a template called search?

    When you return base.Index(Model) it will return only the default template for the content item eg 17070, whne you return CurrentTemplate(Model) then Umbraco will use either the default template or the template requested via ?altTemplate=aliasoftemplatetouse

    So I'm just wondering if the custom routing is successfully making it to your controller and it can't work out which template to return or whether it's not making it to your template and trying to use the default template for 17070 and not finding one?

    regards

    marc

  • Nadia 45 posts 122 karma points
    May 04, 2020 @ 19:48
    Nadia
    0

    Yes it reaches the search action (I tested with the index one as well)

    Yes the node has a default template, this is what I thought it would use.

    I don't have a "search" template, as the template is the name of the doc type eg "AccommodationSearchResultsPage". Do I need a different template setup?

  • Marc Goodson 2155 posts 14408 karma points MVP 9x c-trib
    May 05, 2020 @ 08:24
    Marc Goodson
    100

    Hi Nadia

    When you return CurrentTemplate() (and this is what the base.Index() calls in the underlying RenderMvcController implementation) - Umbraco reads the 'action' name that from the controller that is being executed and uses this as the name of the template to render - the CurrentTemplate method checks whether this file exists on disk and throws an error if it does not.

    In your example if you route via the Search Action - the the template being looked for is called Search - and you'd need to have a Search.cshtml template on disk for it to work...

    ... now interestingly if you route the request via the Index action, then CurrentTemplate is looking for an 'Index' template, which is unexpected, as the 'default implementation' of RenderMVCController requests that aren't custom routed, would have it's action to be set to the name of the default template the page is published with... however when you custom route in this fashion you bypass the steps in the core that would set this for you.

    Therefore the options for working around this are to either:

    a) Create a template that matches your action or vice versa - use an action name that matches your template name b) don't use CurrentTemplate and instead return the View directly from your controller:

    eg:

    return View("~/Views/home.cshtml",page);
    

    c) set the action name to match the template before using CurrentTemplate

         public ActionResult Index(ContentModel model, string type, string region)
                    {
                       //hardcode 
                        ControllerContext.RouteData.Values["action"] = "home";
                        //or with db lookup
                        //ControllerContext.RouteData.Values["action"] = model.Content.GetTemplateAlias();
                        AccommodationSearchResultsPage page = new AccommodationSearchResultsPage(model.Content)
                        {
                            Region = region,
                            Type = type
                        };
    
                        return CurrentTemplate(page);
            }
    

    (also in your example above in the Search action you are not returning your custom page viewmodel, eg return base.CurrentTemplate(model.Content); should be return base.CurrentTemplate(page);

    regards

    Marc

Please Sign in or register to post replies

Write your reply to:

Draft