Copied to clipboard

Flag this post as spam?

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


  • Tom 34 posts 154 karma points
    Dec 29, 2017 @ 10:21
    Tom
    0

    IContentFinder to handle 404's doc types with no template

    Hi all, I've made an implementation of the IContentFinder to pick up on 404's and redirect them to a desired node. Everything work's fine when I set the contentRequest.PublishedContent to the node I want to display when a 404 occurs However if the path of a URL is set a node of which the document type has no template then I get to see the standard 404 notification (No template exists to render the document at url '/submitted-contact-forms/').

    I've tried using contentRequest.SetIsInitialPublishedContent() after I assigned my 404 node to contentRequest.PublishedContent but no luck.

    Here's the simplified version of my code;

    public class _404iLastChanceFinder : IContentFinder {
        public bool TryFindContent(PublishedContentRequest contentRequest) {
            if (contentRequest.Is404) {
                var home = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByRoute("/");
                var notFoundNode =  home.Children.FirstOrDefault(x => x.DocumentTypeAlias == "error_404");
    
                if (notFoundNode != null) {
                    contentRequest.SetResponseStatus(404, notFoundNode.HasProperty("title") ? notFoundNode.GetPropertyValue("title").ToString() : "404");
                    contentRequest.PublishedContent = notFoundNode;
                }
    
                 return contentRequest.PublishedContent != null;
            } else {
                return false;
            }
        }
    }
    

    Hooked it up via the ApplicationEventHandler

    public class UmbracoApplication : ApplicationEventHandler {
        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) {
            ContentLastChanceFinderResolver.Current.SetFinder(new _404iLastChanceFinder());
        }
    }
    
  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Dec 29, 2017 @ 11:25
    Dave Woestenborghs
    0

    Hi Tom,

    This is the code we have for serving a page for 404 requests.

    Contentfinder :

    using Umbraco.Core.Configuration;
        using Umbraco.Web;
        using Umbraco.Web.Routing;
    
        /// <summary>
        /// The four oh four content finder.
        /// </summary>
        internal class FourOhFourContentFinder : IContentFinder
        {
            /// <summary>
            /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
            /// </summary>
            /// <param name="contentRequest">The <c>PublishedContentRequest</c>.</param>
            /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
            /// <remarks>Optionally, can also assign the template or anything else on the document request, although that is not required.</remarks>
            public bool TryFindContent(PublishedContentRequest contentRequest)
            {
                // Check request is a 404
                if (contentRequest.Is404)
                {
                    return contentRequest.PublishedContent != null;
                }
    
                var errorPage =
                    UmbracoContext.Current.ContentCache.GetSingleByXPath($"//error_404[@isDoc]");
    
                if (errorPage != null)
                {
                    // set content for the 404 page
                    contentRequest.PublishedContent = errorPage;
    
                    // Set Response Status to be HTTP 404
                    contentRequest.SetIs404();
                }
    
                return false;
            }
        }
    

    Application start

    public class UmbracoApplication : ApplicationEventHandler {
        protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) {
           ContentFinderResolver.Current.InsertTypeBefore<ContentFinderByNotFoundHandlers, FourOhFourContentFinder>();
        }
    }
    

    This works perfectly for us.

    Dave

  • Tom 34 posts 154 karma points
    Dec 29, 2017 @ 12:20
    Tom
    0

    Hi Dave,

    Thanks for the reply. In the code you provided there is a return contentRequest.PublishedContent != null; before assigning the errorpage node thus you still get redirected to the default 404 page. Remove the return but the problem remains unfortunately.

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Dec 29, 2017 @ 12:25
    Dave Woestenborghs
    0

    Hi Tom,

    Does your 404 page have a template assigned ? It needs a template to be rendered.

    Dave

  • Tom 34 posts 154 karma points
    Dec 29, 2017 @ 12:36
    Tom
    0

    I overlooked something; I've hooked my implementation of the IContentFinder to the ContentLastChanceFinderResolver on application_start where your solution does so on the ContentFinderResolver.

    Tried your solution again but unfortunately, if a page that's based on a document type without a template get's requested the FourOhFourContentFinder doesn't even get called and I still get to see the default 404 page.

    My 404 page does have a template. Request to non-existent pages like example.com/foobartest123 get to see this custom 404 page

  • Tom 34 posts 154 karma points
    Dec 29, 2017 @ 12:42
    Tom
    0

    I've noticed another subtle difference between how the implementation of the IContentFinder is hooked up inside the application_start. I did so by using the ContentLastChanceFinderResolver while yours used the ContentFinderResolver.

    Tried it again but unfortunately a page request that has it's document type based on one without a template get's redirected to the default 404 page. Whereas e.g. the non-existent page example.com/foobar get's to see my custom 404 page (it does have a template). Whilst debugging i've noticed that the FourOhFourContentFinder doesn't even get called.

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Dec 29, 2017 @ 12:55
    Dave Woestenborghs
    0

    Hi Tom,

    Maybe it's related to some config :

    I notice that we have removed this from config/404handlers.config

    <notFound assembly="umbraco" type="SearchForTemplate"/>
    

    In config/umbracoSettings.config we have the following set trySkipIisCustomErrors to true in the web.routing section

    In our web.config we have the following tag in our system.webServer section

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

    Can you check your configuration ?

    Dave

  • Tom 34 posts 154 karma points
    Dec 29, 2017 @ 13:23
    Tom
    0

    Hi Dave,

    I've changed the 404handlers.config and set the trySkipIisCustomErrors to true. PassThrough value was already there. Still no luck. I'm going to try this out on a clean umbraco installation to see if I've missed something.

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Dec 29, 2017 @ 12:25
    Dave Woestenborghs
    0

    Hi Tom,

    This is for when the request is already marked as 404. So there is no need to set the 404 page again.

    Dave

Please Sign in or register to post replies

Write your reply to:

Draft