private SiteMapNode GetParentNode(SiteMapNode node, ContentMap map)
        {
            WebsiteNode site;
            IContentMapEntityUrlProvider urlProvider;

            using (PerformanceProfiler.Instance.StartMarker(PerformanceMarkerName.SiteMapProvider, PerformanceMarkerArea.Cms, PerformanceMarkerTagName.GetParentNodes))
            {
                if (!TryGetWebsite(map, out site, out urlProvider))
                {
                    return(base.GetParentNode(node));
                }

                ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("key={0}", node.Key));

                // When searching for parent page, it doesn't matter if we look for root or content page, both will have the same parent page.
                var languageContext = HttpContext.Current.GetContextLanguageInfo();
                var mappingResult   = ContentMapUrlMapping.LookupPageByUrlPath(site, node.Url, ContentMapUrlMapping.WebPageLookupOptions.Any, languageContext);

                // Ignore IsUnique to find any avaiable parent node
                if (mappingResult.Node == null || mappingResult.Node.Parent == null || mappingResult.Node.Parent.IsReference)
                {
                    return(null);
                }

                return(ReturnNodeIfAccessible(GetNode(map, mappingResult.Node.Parent, urlProvider), () => null));
            }
        }
        private SiteMapNode FindSiteMapNode(string rawUrl, ContentMap map, int counter = 0, bool excludeFromSecurityValidation = false)
        {
            using (PerformanceProfiler.Instance.StartMarker(PerformanceMarkerName.SiteMapProvider, PerformanceMarkerArea.Cms, PerformanceMarkerTagName.FindSiteMapNode))
            {
                counter++;
                WebsiteNode site;
                IContentMapEntityUrlProvider urlProvider;

                if (!TryGetWebsite(map, out site, out urlProvider))
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (1)cannot find WebsiteNode");
                    return(base.FindSiteMapNode(rawUrl));
                }

                var    httpContext = HttpContext.Current;
                string currentNodeUrl;

                // Allow override of current site map node using special route param.
                if (httpContext != null &&
                    httpContext.Request.RawUrl == rawUrl &&
                    TryGetCurrentNodeUrlFromRouteData(httpContext, out currentNodeUrl) &&
                    currentNodeUrl != rawUrl && counter < 5000)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (2)override url");
                    return(FindSiteMapNode(currentNodeUrl, map, counter, excludeFromSecurityValidation));
                }

                var clientUrl = ExtractClientUrlFromRawUrl(rawUrl);

                // Find any possible SiteMarkerRoutes (or other IPortalContextRoutes) that match this path.
                string routeMatch  = RouteTable.Routes.GetPortalContextPath(map, site, clientUrl.Path);
                var    contextPath = routeMatch ?? clientUrl.Path;
                if (routeMatch != null)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (3)FOUND route");
                }

                var languageContext = httpContext.GetContextLanguageInfo();
                // If the URL matches a web page, try to look up that page and return a node.
                var mappingResult = ContentMapUrlMapping.LookupPageByUrlPath(site, contextPath, ContentMapUrlMapping.WebPageLookupOptions.LanguageContentOnly, languageContext);

                if (mappingResult.Node != null && mappingResult.IsUnique)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (4)FOUND PAGE");
                    return(GetAccessibleNodeOrAccessDeniedNode(map, mappingResult.Node, urlProvider, excludeFromSecurityValidation));
                }
                else if (!mappingResult.IsUnique)
                {
                    return(GetNotFoundNode(map, site, urlProvider));
                }

                // If the URL matches a web file, try to look up that file and return a node.
                var file = ContentMapUrlMapping.LookupFileByUrlPath(site, clientUrl.Path, languageContext);

                if (file != null)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (5)FOUND FILE");
                    return(GetAccessibleNodeOrAccessDeniedNode(map, file, urlProvider, excludeFromSecurityValidation));
                }

                // If there is a pageid Guid on the querystring, try to look up a web page by
                // that ID and return a node.
                Guid pageid;

                if (TryParseGuid(clientUrl.QueryString["pageid"], out pageid))
                {
                    WebPageNode pageById;

                    if (map.TryGetValue(new EntityReference("adx_webpage", pageid), out pageById))
                    {
                        ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (6)FOUND pageID");
                        return(GetAccessibleNodeOrAccessDeniedNode(map, pageById, urlProvider, excludeFromSecurityValidation));
                    }
                }

                // If the above lookups failed, try find a node in any other site map providers.
                foreach (SiteMapProvider subProvider in SiteMap.Providers)
                {
                    // Skip this provider if it is the same as this one.
                    if (subProvider.Name == Name)
                    {
                        continue;
                    }

                    // Check if the provider has solution dependencies
                    var solutionDependent = subProvider as ISolutionDependent;

                    if (solutionDependent != null)
                    {
                        if (map.Solution.Solutions.Intersect(solutionDependent.RequiredSolutions).Count() != solutionDependent.RequiredSolutions.Count())
                        {
                            continue;
                        }
                    }

                    var node = subProvider.FindSiteMapNode(clientUrl.PathWithQueryString);

                    if (node != null)
                    {
                        ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (7)FOUND other provider");
                        return(node);
                    }
                }

                ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (8)NOT FOUND");
                return(GetNotFoundNode(map, site, urlProvider));
            }
        }
        private SiteMapNodeCollection GetChildNodes(SiteMapNode node, ContentMap map)
        {
            WebsiteNode site;
            IContentMapEntityUrlProvider urlProvider;

            using (PerformanceProfiler.Instance.StartMarker(PerformanceMarkerName.SiteMapProvider, PerformanceMarkerArea.Cms, PerformanceMarkerTagName.GetChildNodes))
            {
                if (!TryGetWebsite(map, out site, out urlProvider))
                {
                    return(base.GetChildNodes(node));
                }

                var children = new List <SiteMapNode>();

                // Shorcuts do not have children, may have the same Url as a web page.
                if (IsShortcutNode(node))
                {
                    return(new SiteMapNodeCollection());
                }

                // SiteMap is not language-aware, so the node.Url will always be URL of the root WebPage, so look for root.
                var langContext  = HttpContext.Current.GetContextLanguageInfo();
                var filterResult = ContentMapUrlMapping.LookupPageByUrlPath(site, node.Url, ContentMapUrlMapping.WebPageLookupOptions.RootOnly, langContext);

                if (filterResult.Node != null && filterResult.IsUnique)
                {
                    var portal  = PortalContext;
                    var context = portal.ServiceContext;

                    foreach (var child in filterResult.Node.WebPages)
                    {
                        // Only get children pages who match the current active language.
                        var childNode = IsValidLanguageContentPage(child, langContext) ? GetNode(map, child, HttpStatusCode.OK, urlProvider) : null;

                        if (childNode == null)
                        {
                            continue;
                        }

                        if (ChildNodeValidator.Validate(context, childNode))
                        {
                            children.Add(childNode);
                        }
                    }

                    foreach (var file in filterResult.Node.WebFiles)
                    {
                        var childNode = GetNode(map, file, urlProvider);

                        if (ChildNodeValidator.Validate(context, childNode))
                        {
                            children.Add(childNode);
                        }
                    }

                    foreach (var shortcut in filterResult.Node.Shortcuts)
                    {
                        var childNode = GetNode(map, shortcut, urlProvider);

                        if (childNode != null && ChildNodeValidator.Validate(context, childNode))
                        {
                            children.Add(childNode);
                        }
                    }
                }

                // Append values from other site map providers.
                foreach (SiteMapProvider subProvider in SiteMap.Providers)
                {
                    // Skip this provider if it is the same as this one.
                    if (subProvider.Name == Name)
                    {
                        continue;
                    }

                    // Check if the provider has solution dependencies
                    var solutionDependent = subProvider as ISolutionDependent;

                    if (solutionDependent != null)
                    {
                        if (map.Solution.Solutions.Intersect(solutionDependent.RequiredSolutions).Count() != solutionDependent.RequiredSolutions.Count())
                        {
                            continue;
                        }
                    }

                    var subProviderChildNodes = subProvider.GetChildNodes(node);

                    if (subProviderChildNodes == null)
                    {
                        continue;
                    }

                    foreach (SiteMapNode childNode in subProviderChildNodes)
                    {
                        children.Add(childNode);
                    }
                }

                children.Sort(new SiteMapNodeDisplayOrderComparer());

                return(new SiteMapNodeCollection(children.ToArray()));
            }
        }