Copied to clipboard

Flag this post as spam?

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


  • Deane 14 posts 54 karma points
    Jan 04, 2019 @ 23:28
    Deane
    0

    Running a default controller on content with no template

    I have a weird scenario for which I would like to execute the same controller for every single inbound request and never invoke the standard Umbraco templating system.

    I have found DefaultRenderMvcControllerResolver and assigned my default controller, which is good.

    However, if a piece of content doesn't have a template assigned, it throws an error before getting to the Index action of the controller is hit (meaning, it never gets to the controller...)

    No template exists to render the document at url '/whatever/'.
    

    Umbraco must identify the content being addressed, retrieve it, then check for the assignment of a template, then not hand it to my controller if it has no template.

    This means I need to make an empty template for every Document Type. I can do this, but it seems kind of wasteful.

    How can I tell Umbraco "None of the content will have templates. Just run my controller anyway..."?

  • Paul Wright (suedeapple) 208 posts 581 karma points
    Jan 05, 2019 @ 00:18
    Paul Wright (suedeapple)
    0

    If this is for EVERY inbound request, then a HTTP Module might be a more efficient approach.

  • Deane 14 posts 54 karma points
    Jan 05, 2019 @ 16:26
    Deane
    0

    I should have worded this better.

    I want to run code for every successful request to a known content object.

    Specifically, I want...

    1. ...the controller to get "handed" an existing content object
    2. ...a 404 to still be a 404

    Sorry. I was unclear.

  • Marc Goodson 887 posts 5808 karma points MVP 4x c-trib
    Jan 05, 2019 @ 12:07
    Marc Goodson
    0

    Hi Deane

    When using the CurrentTemplate helper in a RenderMvcController, a check is made for the existence of the view:

      protected ActionResult CurrentTemplate<T>(T model)
            {
                var template = ControllerContext.RouteData.Values["action"].ToString();
                if (EnsurePhsyicalViewExists(template) == false)
                    throw new Exception("No physical template file was found for template " + template);
                return View(template, model);
            } 
    

    which I thought was the error you were seeing

    if so you could just work around this by having your own helper for returning the Current Template without the physical view check... or just directly in your CustomRenderMvcController like so:

    public class CustomRenderMvcController : RenderMvcController
    {
        public override ActionResult Index(RenderModel model)
        {
            var template = ControllerContext.RouteData.Values["action"].ToString();
            return View(template, model);
        }
    }
    

    but actually I've spun up a copy of 7.12.4 to test this, and you are right, the index doesn't get hit, at the point where Umbraco assembles the PublishedContentRequest item associated with the request, it checks for a template... and regardless if it's hijacked, returns the not found handler, that displays the message you see.

    https://github.com/umbraco/Umbraco-CMS/blob/dd6e764588d22ef2b7bce01fd504ece89834f181/src/Umbraco.Web/Routing/PublishedContentNotFoundHandler.cs

    I think it is meant to work though; looking at this comment here:

    https://github.com/umbraco/Umbraco-CMS/blob/dd6e764588d22ef2b7bce01fd504ece89834f181/src/Umbraco.Web/Mvc/RenderRouteHandler.cs#L295

    There is a published content prepared event, that we can handle before this check, but it appears the HasTemplate is read only, otherwise we could just set it to true to avoid this,

    https://github.com/umbraco/Umbraco-CMS/blob/dd6e764588d22ef2b7bce01fd504ece89834f181/src/Umbraco.Web/Routing/PublishedContentRequest.cs

    hmm, sorry, interesting, but not very helpful reply!

    regards

    Marc

  • Deane 14 posts 54 karma points
    Jan 05, 2019 @ 16:24
    Deane
    0

    You must have edited your reply, because I tried the first version of your post, and came back here to note that it wasn't quite what I was looking for -- then I saw the expanded version. :-)

    There are two checks, it seems:

    1. That a template is assigned to the content
    2. That a physical file for that template exists

    I'm failing on that first check. I've actually deleted the underlying file, and it doesn't seem to matter, because the execution never gets to the point where it even looks for the physical file. It gets uptight when it finds that nothing is assigned.

    Not a big deal -- I'll just create a "Null Template" and assign it to everything.

  • Marc Goodson 887 posts 5808 karma points MVP 4x c-trib
    Jan 05, 2019 @ 17:31
    Marc Goodson
    100

    Hi Deane

    Yes I sort of answered first without thinking, and then thought, hmm, he's not actually hitting his controller index action at all, hmm, and thought I'd try it out...

    Anyway I think you can work around it without having to set the templates explicitly in the backoffice for ALL the document types.

    if you have one empty template in the BackOffice, then you can use the PublishedContentRequest_Prepared event to set that template in code for all your requests. eg:

            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
                { 
    
                    DefaultRenderMvcControllerResolver.Current.SetDefaultControllerType(typeof(CustomRenderMvcController));
                    PublishedContentRequest.Prepared += PublishedContentRequest_Prepared;
    
                }
    
      private void PublishedContentRequest_Prepared(object sender, EventArgs e)
            {
                PublishedContentRequest request = sender as PublishedContentRequest;
                request.TrySetTemplate("aliasOfEmptyTemplate");
            }
    

    That enables me to hit the Index Action of the the custom Default RenderMvcController, when the document has no template assigned...

    regards

    Marc

  • Deane 14 posts 54 karma points
    Jan 08, 2019 @ 15:39
    Deane
    0

    This worked beautifully. Thank you.

  • Deane 14 posts 54 karma points
    Jan 08, 2019 @ 16:31
    Deane
    0

    I did find another issue: if there's no template assigned, Umbraco doesn't generate a URL for it. Under the "Info" tab, you get:

    This document is published but is not in the cache

  • Søren Kottal 396 posts 2409 karma points MVP c-trib
    Jan 08, 2019 @ 21:01
    Søren Kottal
    0

    Hi Deane

    It should generate the URL anyway, try saving and publishing again to purge the cache.

  • Deane 14 posts 54 karma points
    Jan 08, 2019 @ 21:32
    Deane
    0

    I see what happened.

    When I publish the site from dev out of VS, it's over-writing the umbraco.config file in App_Data. My dev instance has different content, so the umbraco.config running in production no longer matches what's in the database.

    I deleted that file, then republished the entire site, and all is good now.

    But, follow-on question: should I not publish App_Data? I've found there are files in here that need to be published -- I have paths in web.config to files in NuGetBackup, for instance.

    What am I doing wrong here? Do exclude App_Data or not?

Please Sign in or register to post replies

Write your reply to:

Draft