Copied to clipboard

Flag this post as spam?

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


  • David Amri 183 posts 686 karma points
    Jan 28, 2019 @ 14:01
    David Amri
    0

    Custom 404 handler not redirecting when template is missing

    Hi,

    I have a custom 404 handler because of a multi site setup. This work fine if the node isn't found but if the node exists but does not have a template it will try to load the page anyway. How can I check if the requested page does not have a template and show the custom 404 page. I'm having a hard time getting this to work. I'm guessing the contentRequest are unable to check if the node has a template as the it will only run the code if the node is missing...

    using System.Linq;
    using Umbraco.Core;
    using Umbraco.Web.Routing;
    
    namespace MyClass.Controllers
    {
        /// <summary>
        /// Umbraco content finder implementation for 404 pages in multi-lingual sites
        /// Assumes each site has a document type with alias of "PageNotFound" in the root of the site (under home node)
        /// </summary>
        public class PageNotFound : IContentFinder
        {
            /// <summary>
            /// Used to find the correct 404 page when a page cannot be found in Umbraco
            /// </summary>
            /// <param name="contentRequest">The current Umbraco context</param>
            /// <returns>The 404 page</returns>
            public bool TryFindContent(PublishedContentRequest contentRequest)
            {
                //Check request cannot be found
                if (contentRequest.PublishedContent == null)
                {
                    var domain = contentRequest.UmbracoDomain.RootContentId;
    
                    // Master page must have domain set
                    if (domain != null)
                    {
                        var home = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(domain.Value);
    
                        if (home != null)
                        {
                            //Get the 404 node
                            var notFoundNode = home.Children.FirstOrDefault(x => x.DocumentTypeAlias == "pageNotFound_d");
    
                            if (notFoundNode != null)
                            {
                                //Set Response Status to be HTTP 404
                                contentRequest.SetResponseStatus(404, "Not Found");
    
                                //Set the node to be the not found node
                                contentRequest.PublishedContent = notFoundNode;
                            }
                        }
                    }
                }
    
                return contentRequest.PublishedContent != null;
            }
    
            /// <summary>
            /// Also need to register the handler in OnApplicationStarting
            /// </summary>
            public class StartUpApplication : ApplicationEventHandler
            {
                protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
                {
                    ContentFinderResolver.Current.InsertTypeBefore<ContentFinderByNotFoundHandlers, PageNotFound>();
                }
            }
        }
    }
    

    Best regards /David

  • Dirk De Grave 4532 posts 5976 karma points MVP 3x admin
    Jan 28, 2019 @ 14:12
    Dirk De Grave
    1

    Can't comment on the "real" question at the moment, but you should remove the part about setting response code, as it will be done for you if you register it differently:

    ContentLastChanceFinderResolver.Current.SetFinder(new PageNotFound());
    

    See https://our.umbraco.com/documentation/reference/routing/request-pipeline/icontentfinder#notfoundhandlers

  • David Amri 183 posts 686 karma points
    Jan 29, 2019 @ 08:55
    David Amri
    0

    Hi Dirk,

    When changing how I register the PageNotFound code it shows me the custom 404 page when no template is set, wich is great. But, if I browse to a node that doesn't exists I will get a iis error instead of the custom 404 page with a 500 response?

    In the web.config I have set the httpsErrors to:

    <httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough">
    

    Could this be the source of the problem now?

  • Dirk De Grave 4532 posts 5976 karma points MVP 3x admin
    Jan 29, 2019 @ 09:51
    Dirk De Grave
    0

    Have you checked the part about web.routing inside umbracoSettings.config? there should be comments on how to configure it inside the config file

  • David Amri 183 posts 686 karma points
    Jan 29, 2019 @ 10:01
    David Amri
    0

    Yes, they look like this:

    <web.routing 
        trySkipIisCustomErrors="true" 
        internalRedirectPreservesTemplate="false" 
        disableAlternativeTemplates="false" 
        disableFindContentByIdPath="false" 
        umbracoApplicationUrl="" 
        disableRedirectUrlTracking="true">
    </web.routing>
    
  • Dirk De Grave 4532 posts 5976 karma points MVP 3x admin
    Jan 29, 2019 @ 10:04
    Dirk De Grave
    0

    this is our current web.config settings for httpErrors and seems to work fine in combo with umbracoSettings.config

    <httpErrors existingResponse="Auto" errorMode="Custom">
    

    Have you tried that one? Can't see any other issue to be honest

  • David Amri 183 posts 686 karma points
    Jan 29, 2019 @ 10:31
    David Amri
    0

    Ugh, actually the code below won't run if i navigate to a url that has no content, only if the node has no template. I'm trying to run the code when either the node is missing or the node has no template.

    using System.Linq;
    using Umbraco.Core;
    using Umbraco.Web.Routing;
    
    namespace PyramidWebsiteClassTests
    {
        /// <summary>
        /// Umbraco content finder implementation for 404 pages in multi-lingual sites
        /// Assumes each site has a document type with alias of "PageNotFound" in the root of the site (under home node)
        /// </summary>
        public class PageNotFound : IContentFinder
        {
            /// <summary>
            /// Used to find the correct 404 page when a page cannot be found in Umbraco
            /// </summary>
            /// <param name="contentRequest">The current Umbraco context</param>
            /// <returns>The 404 page</returns>
            public bool TryFindContent(PublishedContentRequest contentRequest)
            {
    
                //Check request cannot be found
                if (contentRequest.PublishedContent == null)
                {
                    var domain = contentRequest.UmbracoDomain.RootContentId;
    
                    if (domain != null)
                    {
                        var home = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(domain.Value);
    
                        if (home != null)
                        {
                            //Get the 404 node
                            var notFoundNode = home.Children.FirstOrDefault(x => x.DocumentTypeAlias == "pageNotFound_d");
    
                            if (notFoundNode != null)
                            {
                                //Set Response Status to be HTTP 404
                                //contentRequest.SetResponseStatus(404, "Not Found");
    
                                //Set the node to be the not found node
                                contentRequest.PublishedContent = notFoundNode;
                            }
                        }
                    }
                }
    
                return contentRequest.PublishedContent != null;
            }
    
            /// <summary>
            /// Also need to register the handler in OnApplicationStarting
            /// </summary>
            public class StartUpApplication : ApplicationEventHandler
            {
                protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
                {
                    //ContentFinderResolver.Current.InsertTypeBefore<ContentFinderByNotFoundHandlers, PageNotFound>();
                    ContentLastChanceFinderResolver.Current.SetFinder(new PageNotFound());
                }
            }
        }
    }
    
  • David Amri 183 posts 686 karma points
    Jan 29, 2019 @ 10:45
    David Amri
    0

    I feel stupid... finally found the error. I had commented out the <error404></error404> from umbracoSettings.config. Now when left empty instead it looks like its working on both nodes that are missing or has no template.

    Thanks for your time Dirk.

  • Dirk De Grave 4532 posts 5976 karma points MVP 3x admin
    Jan 29, 2019 @ 10:47
    Dirk De Grave
    0

    Ah, good you got it working!

Please Sign in or register to post replies

Write your reply to:

Draft