/// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="pcr">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public bool TryFindContent(PublishedContentRequest pcr)
        {
            LogHelper.Debug <ContentFinderByLegacy404>("Looking for a page to handle 404.");

            // TODO - replace the whole logic
            var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
                //TODO: The IContentSection should be ctor injected into this class in v8!
                UmbracoConfig.For.UmbracoSettings().Content.Error404Collection.ToArray(),
                //TODO: Is there a better way to extract this value? at least we're not relying on singletons here though
                pcr.RoutingContext.UmbracoContext.HttpContext.Request.ServerVariables["SERVER_NAME"],
                pcr.RoutingContext.UmbracoContext.Application.Services.EntityService,
                new PublishedContentQuery(pcr.RoutingContext.UmbracoContext.ContentCache, pcr.RoutingContext.UmbracoContext.MediaCache),
                pcr.RoutingContext.UmbracoContext.Application.Services.DomainService);

            IPublishedContent content = null;

            if (error404.HasValue)
            {
                LogHelper.Debug <ContentFinderByLegacy404>("Got id={0}.", () => error404.Value);

                content = pcr.RoutingContext.UmbracoContext.ContentCache.GetById(error404.Value);

                LogHelper.Debug <ContentFinderByLegacy404>(content == null
                                ? "Could not find content with that id."
                                : "Found corresponding content.");
            }
            else
            {
                LogHelper.Debug <ContentFinderByLegacy404>("Got nothing.");
            }

            pcr.PublishedContent = content;
            pcr.SetIs404();
            return(content != null);
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="pcr">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public bool TryFindContent(PublishedContentRequest pcr)
        {
            var type    = typeof(THandler);
            var handler = GetHandler(type);

            if (handler == null)
            {
                return(false);
            }

            var url = NotFoundHandlerHelper.GetLegacyUrlForNotFoundHandlers();

            LogHelper.Debug <ContentFinderByNotFoundHandler <THandler> >("Running for legacy url='{0}'.", () => url);

            if (handler.Execute(url) && handler.redirectID > 0)
            {
                LogHelper.Debug <ContentFinderByNotFoundHandler <THandler> >("Handler '{0}' returned id={1}.", () => type.FullName, () => handler.redirectID);

                var content = pcr.RoutingContext.UmbracoContext.ContentCache.GetById(handler.redirectID);

                LogHelper.Debug <ContentFinderByNotFoundHandler <THandler> >(content == null
                                ? "Could not find content with that id."
                                : "Found corresponding content.");

                pcr.PublishedContent = content;
                return(content != null);
            }

            LogHelper.Debug <ContentFinderByNotFoundHandler <THandler> >("Handler '{0}' returned nothing.", () => type.FullName);
            return(false);
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedRequest</c>.
        /// </summary>
        /// <param name="frequest">The <c>PublishedRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public bool TryFindContent(PublishedRequest frequest)
        {
            _logger.Debug <ContentFinderByConfigured404>("Looking for a page to handle 404.");

            // try to find a culture as best as we can
            var errorCulture = CultureInfo.CurrentUICulture;

            if (frequest.HasDomain)
            {
                errorCulture = frequest.Domain.Culture;
            }
            else
            {
                var route = frequest.Uri.GetAbsolutePathDecoded();
                var pos   = route.LastIndexOf('/');
                IPublishedContent node = null;
                while (pos > 1)
                {
                    route = route.Substring(0, pos);
                    node  = frequest.UmbracoContext.ContentCache.GetByRoute(route, culture: frequest?.Culture?.Name);
                    if (node != null)
                    {
                        break;
                    }
                    pos = route.LastIndexOf('/');
                }
                if (node != null)
                {
                    var d = DomainHelper.FindWildcardDomainInPath(frequest.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), node.Path, null);
                    if (d != null)
                    {
                        errorCulture = d.Culture;
                    }
                }
            }

            var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
                _contentConfigSection.Error404Collection.ToArray(),
                _entityService,
                new PublishedContentQuery(frequest.UmbracoContext.PublishedSnapshot, frequest.UmbracoContext.VariationContextAccessor),
                errorCulture);

            IPublishedContent content = null;

            if (error404.HasValue)
            {
                _logger.Debug <ContentFinderByConfigured404>("Got id={ErrorNodeId}.", error404.Value);

                content = frequest.UmbracoContext.ContentCache.GetById(error404.Value);

                _logger.Debug <ContentFinderByConfigured404>(content == null
                    ? "Could not find content with that id."
                    : "Found corresponding content.");
            }
            else
            {
                _logger.Debug <ContentFinderByConfigured404>("Got nothing.");
            }

            frequest.PublishedContent = content;
            frequest.Is404            = true;
            return(content != null);
        }
        void HandlePageNotFound(PublishedContentRequest docRequest)
        {
            var url = NotFoundHandlerHelper.GetLegacyUrlForNotFoundHandlers();

            LogHelper.Debug <ContentFinderByNotFoundHandlers>("Running for legacy url='{0}'.", () => url);

            foreach (var handler in GetNotFoundHandlers())
            {
                IContentFinder finder      = null;
                var            handlerName = handler.GetType().FullName;

                LogHelper.Debug <ContentFinderByNotFoundHandlers>("Handler '{0}'.", () => handlerName);

                // replace with our own implementation
                if (handler is global::umbraco.SearchForAlias)
                {
                    finder = new ContentFinderByUrlAlias();
                }
                else if (handler is global::umbraco.SearchForProfile)
                {
                    finder = new ContentFinderByProfile();
                }
                else if (handler is global::umbraco.SearchForTemplate)
                {
                    finder = new ContentFinderByNiceUrlAndTemplate();
                }
                else if (handler is global::umbraco.handle404)
                {
                    finder = new ContentFinderByLegacy404();
                }

                if (finder != null)
                {
                    var finderName = finder.GetType().FullName;
                    LogHelper.Debug <ContentFinderByNotFoundHandlers>("Replace handler '{0}' by new finder '{1}'.", () => handlerName, () => finderName);
                    if (finder.TryFindContent(docRequest))
                    {
                        // do NOT set docRequest.PublishedContent again here as
                        // it would clear any template that the finder might have set
                        LogHelper.Debug <ContentFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
                        if (docRequest.Is404)
                        {
                            LogHelper.Debug <ContentFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
                        }

                        // if we found a document, break, don't look at more handler -- we're done
                        break;
                    }

                    // if we did not find a document, continue, look at other handlers
                    continue;
                }

                // else it's a legacy handler, run

                if (handler.Execute(url) && handler.redirectID > 0)
                {
                    var redirectId = handler.redirectID;
                    docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);

                    if (!docRequest.HasPublishedContent)
                    {
                        LogHelper.Debug <ContentFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
                        break;
                    }

                    LogHelper.Debug <ContentFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);

                    if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
                    {
                        LogHelper.Debug <ContentFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
                        docRequest.Is404 = true;
                    }

                    //// check for caching
                    //if (handler.CacheUrl)
                    //{
                    //    if (url.StartsWith("/"))
                    //        url = "/" + url;

                    //    var cacheKey = (currentDomain == null ? "" : currentDomain.Name) + url;
                    //    var culture = currentDomain == null ? null : currentDomain.Language.CultureAlias;
                    //    SetCache(cacheKey, new CacheEntry(handler.redirectID.ToString(), culture));

                    //    HttpContext.Current.Trace.Write("NotFoundHandler",
                    //        string.Format("Added to cache '{0}', {1}.", url, handler.redirectID));
                    //}

                    // if we found a document, break, don't look at more handler -- we're done
                    break;
                }

                // if we did not find a document, continue, look at other handlers
            }
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="pcr">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public bool TryFindContent(PublishedContentRequest pcr)
        {
            LogHelper.Debug <ContentFinderByLegacy404>("Looking for a page to handle 404.");

            // try to find a culture as best as we can
            var errorCulture = CultureInfo.CurrentUICulture;

            if (pcr.HasDomain)
            {
                errorCulture = CultureInfo.GetCultureInfo(pcr.UmbracoDomain.LanguageIsoCode);
            }
            else
            {
                var route = pcr.Uri.GetAbsolutePathDecoded();
                var pos   = route.LastIndexOf('/');
                IPublishedContent node = null;
                while (pos > 1)
                {
                    route = route.Substring(0, pos);
                    node  = pcr.RoutingContext.UmbracoContext.ContentCache.GetByRoute(route);
                    if (node != null)
                    {
                        break;
                    }
                    pos = route.LastIndexOf('/');
                }
                if (node != null)
                {
                    var d = DomainHelper.FindWildcardDomainInPath(pcr.RoutingContext.UmbracoContext.Application.Services.DomainService.GetAll(true), node.Path, null);
                    if (d != null && string.IsNullOrWhiteSpace(d.LanguageIsoCode) == false)
                    {
                        errorCulture = CultureInfo.GetCultureInfo(d.LanguageIsoCode);
                    }
                }
            }

            // TODO - replace the whole logic
            var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
                //TODO: The IContentSection should be ctor injected into this class in v8!
                UmbracoConfig.For.UmbracoSettings().Content.Error404Collection.ToArray(),
                pcr.RoutingContext.UmbracoContext.Application.Services.EntityService,
                new PublishedContentQuery(pcr.RoutingContext.UmbracoContext.ContentCache, pcr.RoutingContext.UmbracoContext.MediaCache),
                errorCulture);

            IPublishedContent content = null;

            if (error404.HasValue)
            {
                LogHelper.Debug <ContentFinderByLegacy404>("Got id={0}.", () => error404.Value);

                content = pcr.RoutingContext.UmbracoContext.ContentCache.GetById(error404.Value);

                LogHelper.Debug <ContentFinderByLegacy404>(content == null
                                ? "Could not find content with that id."
                                : "Found corresponding content.");
            }
            else
            {
                LogHelper.Debug <ContentFinderByLegacy404>("Got nothing.");
            }

            pcr.PublishedContent = content;
            pcr.SetIs404();
            return(content != null);
        }
        private static void HandlePageNotFound(PublishedContentRequest docRequest)
        {
            var url = NotFoundHandlerHelper.GetLegacyUrlForNotFoundHandlers();

            LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Running for legacy url='{0}'.", () => url);

            var handler     = NotFoundHandlerHelper.GetNotFoundLastChanceHandler();
            var handlerName = handler.GetType().FullName;

            LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}'.", () => handlerName);

            var finder = NotFoundHandlerHelper.SubsituteFinder(handler);

            if (finder != null)
            {
                var finderName = finder.GetType().FullName;
                LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Replace handler '{0}' by new finder '{1}'.", () => handlerName, () => finderName);

                // can't find a document => exit
                if (finder.TryFindContent(docRequest) == false)
                {
                    return;
                }

                // found a document => we're done

                // in theory an IContentFinder can return true yet set no document
                // but none of the substitued finders (see SubstituteFinder) do it.

                // do NOT set docRequest.PublishedContent again here
                // as it would clear any template that the finder might have set

                LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
                if (docRequest.Is404)
                {
                    LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
                }

                LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => docRequest.PublishedContent.Id);
                return;
            }

            // else it's a legacy handler, run

            // can't find a document => exit
            if (handler.Execute(url) == false || handler.redirectID <= 0)
            {
                return;
            }

            // found a document ID => ensure it's a valid document
            var redirectId = handler.redirectID;

            docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);

            if (docRequest.HasPublishedContent == false)
            {
                // the handler said it could handle the url, and returned a content ID
                // yet that content ID is invalid... exit.

                LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
                return;
            }

            // found a valid document => return

            LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);

            if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
            {
                LogHelper.Debug <ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
                docRequest.Is404 = true;
            }
        }