Exemplo n.º 1
0
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            if (!_externalReviewOptions.IsEnabled)
            {
                return(null);
            }

            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (string.IsNullOrWhiteSpace(nextSegment.Next))
            {
                return(null);
            }

            if (!string.Equals(nextSegment.Next, _externalReviewOptions.ContentPreviewUrl, StringComparison.CurrentCultureIgnoreCase))
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsPreviewableLink())
            {
                return(null);
            }

            if (externalReviewLink.VisitorGroups != null)
            {
                System.Web.HttpContext.Current.Items["ImpersonatedVisitorGroupsById"] = externalReviewLink.VisitorGroups;
            }

            // PIN code security check, if user is not authenticated, then redirect to login page
            if (!_externalLinkPinCodeSecurityHandler.UserHasAccessToLink(externalReviewLink))
            {
                _externalLinkPinCodeSecurityHandler.RedirectToLoginPage(externalReviewLink);
                return(null);
            }

            try
            {
                var page = _projectContentResolver.TryGetProjectPageVersion(externalReviewLink, content,
                                                                            segmentContext.QueryString);

                segmentContext.RemainingPath = nextSegment.Remaining;

                // set ContentLink in DataTokens to make IPageRouteHelper working
                segmentContext.RouteData.DataTokens[RoutingConstants.NodeKey] = page.ContentLink;
                ExternalReview.Token     = token;
                ExternalReview.ProjectId = externalReviewLink.ProjectId;

                return(page);
            }
            catch
            {
                return(null);
            }
        }
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (nextSegment.Next != _externalReviewOptions.ContentIframeEditUrlSegment)
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsEditableLink())
            {
                return(null);
            }

            try
            {
                var page = _contentLoader.Get <IContent>(externalReviewLink.ContentLink);
                segmentContext.RemainingPath = nextSegment.Remaining;

                segmentContext.ContextMode = ContextMode.Edit;
                ExternalReview.Token       = token;

                return(page);
            }
            catch
            {
                return(null);
            }
        }
Exemplo n.º 3
0
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            if (!_externalReviewOptions.IsEnabled)
            {
                return(null);
            }

            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (nextSegment.Next != _externalReviewOptions.ContentIframeEditUrlSegment)
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsEditableLink())
            {
                return(null);
            }

            if (externalReviewLink.VisitorGroups != null)
            {
                System.Web.HttpContext.Current.Items["ImpersonatedVisitorGroupsById"] = externalReviewLink.VisitorGroups;
            }

            var contentReference = externalReviewLink.ContentLink;

            if (externalReviewLink.ProjectId.HasValue)
            {
                var languageID = content.Language.Name;

                var contentContentLink = PreviewUrlResolver.IsGenerated(segmentContext.QueryString) ? content.ContentLink : contentReference;
                contentReference         = _projectContentResolver.GetProjectReference(contentContentLink, externalReviewLink.ProjectId.Value, languageID);
                ExternalReview.ProjectId = externalReviewLink.ProjectId;
            }

            try
            {
                var page = _contentLoader.Get <IContent>(contentReference, content.Language);
                segmentContext.RemainingPath = nextSegment.Remaining;

                // We can't set the Edit context here because it breaks the routing if you have useClaims=true in virtualRoles setting
                // and when you have a custom VirtualRole class that uses IPageRouteHelper to fetch the current language from url
                // segmentContext.ContextMode = ContextMode.Edit;
                segmentContext.RouteData.DataTokens[RoutingConstants.NodeKey] = page.ContentLink;

                ExternalReview.IsEditLink = true;
                ExternalReview.Token      = token;

                return(page);
            }
            catch
            {
                return(null);
            }
        }
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            if (!_externalReviewOptions.IsEnabled)
            {
                return(null);
            }

            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (string.IsNullOrWhiteSpace(nextSegment.Next))
            {
                return(null);
            }

            if (!string.Equals(nextSegment.Next, _externalReviewOptions.ContentPreviewUrl, StringComparison.CurrentCultureIgnoreCase))
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsPreviewableLink())
            {
                return(null);
            }

            var contentReference = externalReviewLink.ContentLink;

            if (externalReviewLink.ProjectId.HasValue)
            {
                var contentContentLink = PreviewUrlResolver.IsGenerated(segmentContext.QueryString) ? content.ContentLink : contentReference;
                contentReference         = _projectContentResolver.GetProjectReference(contentContentLink, externalReviewLink.ProjectId.Value);
                ExternalReview.ProjectId = externalReviewLink.ProjectId;
            }

            try
            {
                var page = _contentLoader.Get <IContent>(contentReference);

                // PIN code security check, if user is not authenticated, then redirect to login page
                if (!_externalLinkPinCodeSecurityHandler.UserHasAccessToLink(externalReviewLink))
                {
                    _externalLinkPinCodeSecurityHandler.RedirectToLoginPage(externalReviewLink);
                    return(null);
                }
                segmentContext.RemainingPath = nextSegment.Remaining;
                ExternalReview.Token         = token;

                return(page);
            }
            catch (ContentNotFoundException)
            {
                return(null);
            }
        }
        private ContentReference TryGetVersionSegment(ref SegmentContext segmentContext)
        {
            var segment        = segmentContext.GetNextValue(segmentContext.RemainingPath);
            var versionSegment = segment.Next;

            if (string.IsNullOrEmpty(versionSegment))
            {
                return(null);
            }

            var re = new Regex("^[0-9]{1,10}_[0-9]{1,10}$");

            if (!re.IsMatch(versionSegment))
            {
                return(null);
            }

            var workId = new ContentReference(versionSegment);

            if (workId.Equals(ContentReference.EmptyReference))
            {
                return(null);
            }

            segmentContext.RemainingPath = segment.Remaining;
            return(workId);
        }
        public override object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            var routedContet = base.RoutePartial(content, segmentContext);

            var segmentPair = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (String.IsNullOrEmpty(segmentPair.Next))
            {
                return(routedContet);
            }

            var facetNames = _facetUrlCreator.GetFacetModels().ToArray();

            var nextSegment = _facetUrlCreator.GetFacetValue(facetNames, segmentPair.Next);

            if (String.IsNullOrEmpty(nextSegment))
            {
                return(routedContet);
            }

            var routeFacets = segmentContext.RouteData.Values[FacetUrlService.RouteFacets] as ConcurrentDictionary <RouteFacetModel, HashSet <object> >;

            if (routeFacets == null)
            {
                segmentContext.RouteData.Values[FacetUrlService.RouteFacets] = new ConcurrentDictionary <RouteFacetModel, HashSet <object> >();
                routeFacets = (ConcurrentDictionary <RouteFacetModel, HashSet <object> >)segmentContext.RouteData.Values[FacetUrlService.RouteFacets];
            }

            AddFacetsToSegmentContext(routeFacets, segmentContext, facetNames, nextSegment, segmentPair.Remaining, null);
            return(routedContet);
        }
        public override object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            var routedContet = base.RoutePartial(content, segmentContext);

            var segmentPair = segmentContext.GetNextValue(segmentContext.RemainingPath);
            if (String.IsNullOrEmpty(segmentPair.Next))
            {
                return routedContet;
            }

            var facetNames = _facetUrlCreator.GetFacetModels().ToArray();

            var nextSegment = _facetUrlCreator.GetFacetValue(facetNames, segmentPair.Next);
            if (String.IsNullOrEmpty(nextSegment))
            {
                return routedContet;
            }

            var routeFacets = segmentContext.RouteData.Values[FacetUrlService.RouteFacets] as ConcurrentDictionary<RouteFacetModel, HashSet<object>>;
            if (routeFacets == null)
            {
                segmentContext.RouteData.Values[FacetUrlService.RouteFacets] = new ConcurrentDictionary<RouteFacetModel, HashSet<object>>();
                routeFacets = (ConcurrentDictionary<RouteFacetModel, HashSet<object>>)segmentContext.RouteData.Values[FacetUrlService.RouteFacets];
            }

            AddFacetsToSegmentContext(routeFacets, segmentContext, facetNames, nextSegment, segmentPair.Remaining, null);
            return routedContet;
        }
Exemplo n.º 8
0
        // this method must convert a partial URL path into a Category entity
        // e.g. the URL "/Northwind/Meat_Poultry"
        // into the category named "Meat/Poultry"
        public object RoutePartial(NorthwindPage content,
                                   SegmentContext segmentContext)
        {
            // get the next part from the URL, i.e. what comes after "/Northwind/"
            var categorySegment = segmentContext.GetNextValue(
                segmentContext.RemainingPath);
            var categoryName = categorySegment.Next;

            // find the matching Category entity
            var db = new Northwind();

            db.Configuration.ProxyCreationEnabled = false;
            db.Configuration.LazyLoadingEnabled   = false;

            var alternativeCategory = categoryName.Replace('_', '/');
            var category            = db.Categories
                                      .Include(c => c.Products)
                                      .SingleOrDefault(c =>
                                                       (c.CategoryName == categoryName) ||
                                                       (c.CategoryName == alternativeCategory));

            if (category != null)
            {
                // store the found Category in the route data
                // so it can be passed into a view
                segmentContext.SetCustomRouteData("category", category);

                // store the remaining path so it could be processed
                // by another partial router, perhaps for Products
                segmentContext.RemainingPath = categorySegment.Remaining;
            }

            return(category);
        }
Exemplo n.º 9
0
        private string TryGetVersionSegment(SegmentContext segmentContext)
        {
            var segment        = segmentContext.GetNextValue(segmentContext.RemainingPath);
            var versionSegment = segment.Next;

            segmentContext.RemainingPath = segment.Remaining;
            return(versionSegment);
        }
Exemplo n.º 10
0
        private SegmentPair ReadNextSegment(SegmentContext segmentContext)
        {
            var segment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            segmentContext.RemainingPath = segment.Remaining;

            return(segment);
        }
        public object RoutePartial(BlogPage content, SegmentContext segmentContext)
        {
            var  nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);
            long blogId;
            var  article = long.TryParse(nextSegment.Next, out blogId) ? BlogManager.Value.GetItem(blogId) : BlogManager.Value.GetItem(nextSegment.Next, true);

            segmentContext.RemainingPath = nextSegment.Remaining;
            return(article);
        }
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            if (!_externalReviewOptions.IsEnabled)
            {
                return(null);
            }

            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (nextSegment.Next != _externalReviewOptions.ContentIframeEditUrlSegment)
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsEditableLink())
            {
                return(null);
            }

            try
            {
                var page = _contentLoader.Get <IContent>(externalReviewLink.ContentLink);
                segmentContext.RemainingPath = nextSegment.Remaining;

                // We can't set the Edit context here because it breaks the routing if you have useClaims=true in virtualRoles setting
                // and when you have a custom VirtualRole class that uses IPageRouteHelper to fetch the current language from url
                // segmentContext.ContextMode = ContextMode.Edit;
                segmentContext.RouteData.DataTokens[RoutingConstants.NodeKey] = page.ContentLink;

                ExternalReview.IsEditLink = true;
                ExternalReview.Token      = token;

                return(page);
            }
            catch
            {
                return(null);
            }
        }
Exemplo n.º 13
0
        public object RoutePartial(ICategoryRoutableContent content, SegmentContext segmentContext)
        {
            var thisSegment = segmentContext.RemainingPath;
            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            while (string.IsNullOrEmpty(nextSegment.Remaining) == false)
            {
                nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            }

            if (string.IsNullOrWhiteSpace(nextSegment.Next) == false)
            {
                var         localizableContent = content as ILocale;
                CultureInfo preferredCulture   = localizableContent?.Language ?? ContentLanguage.PreferredCulture;

                string[] categoryUrlSegments = nextSegment.Next.Split(new [] { CategorySeparator }, StringSplitOptions.RemoveEmptyEntries);
                var      categories          = new List <CategoryData>();

                foreach (var categoryUrlSegment in categoryUrlSegments)
                {
                    var category = CategoryLoader.GetFirstBySegment <CategoryData>(categoryUrlSegment, preferredCulture);

                    if (category == null)
                    {
                        return(null);
                    }

                    categories.Add(category);
                }

                segmentContext.RemainingPath = thisSegment.Substring(0, thisSegment.LastIndexOf(nextSegment.Next, StringComparison.InvariantCultureIgnoreCase));
                segmentContext.SetCustomRouteData(CategoryRoutingConstants.CurrentCategory, categories[0]);
                segmentContext.SetCustomRouteData(CategoryRoutingConstants.CurrentCategories, categories);
                segmentContext.RoutedContentLink = content.ContentLink;
                segmentContext.RoutedObject      = content;

                return(content);
            }

            return(null);
        }
Exemplo n.º 14
0
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            if (!_externalReviewOptions.IsEnabled)
            {
                return(null);
            }

            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (nextSegment.Next != _externalReviewOptions.ContentIframeEditUrlSegment)
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsEditableLink())
            {
                return(null);
            }

            try
            {
                var page = _contentLoader.Get <IContent>(externalReviewLink.ContentLink);
                segmentContext.RemainingPath = nextSegment.Remaining;

                segmentContext.ContextMode = ContextMode.Edit;
                // set ContentLink in DataTokens to make IPageRouteHelper working
                segmentContext.RouteData.DataTokens[RoutingConstants.NodeKey] = page.ContentLink;
                ExternalReview.Token = token;

                return(page);
            }
            catch
            {
                return(null);
            }
        }
Exemplo n.º 15
0
        public object RoutePartial(NewsListPage content, SegmentContext segmentContext)
        {
            var remainingPath = segmentContext.RemainingPath;

            var nextValue = segmentContext.GetNextValue(remainingPath);

            if (int.TryParse(nextValue.Next, out int pageNumber))
            {
                segmentContext.RouteData.Values["nextPage"] = pageNumber;
                segmentContext.RemainingPath = nextValue.Remaining;
            }

            return(content);
        }
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (nextSegment.Next != _externalReviewOptions.ContentIframeEditUrlSegment)
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsEditableLink())
            {
                return(null);
            }

            // HttpContext.Current.Request.RequestContext.SetContextMode(ContextMode.Edit);

            try
            {
                var page = _contentLoader.Get <IContent>(externalReviewLink.ContentLink);
                segmentContext.RemainingPath = nextSegment.Remaining;

                segmentContext.ContextMode = ContextMode.Edit;
                segmentContext.RouteData.DataTokens[RoutingConstants.NodeKey] = page.ContentLink;
                ExternalReview.IsInExternalReviewContext = true;

                return(page);
            }
            catch
            {
                return(null);
            }
        }
Exemplo n.º 17
0
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            if (string.IsNullOrWhiteSpace(nextSegment.Next))
            {
                return(null);
            }

            if (!string.Equals(nextSegment.Next, _externalReviewOptions.ContentPreviewUrl, StringComparison.CurrentCultureIgnoreCase))
            {
                return(null);
            }

            nextSegment = segmentContext.GetNextValue(nextSegment.Remaining);
            var token = nextSegment.Next;

            var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);

            if (!externalReviewLink.IsPreviewableLink())
            {
                return(null);
            }

            try
            {
                var page = _contentLoader.Get <IContent>(externalReviewLink.ContentLink);
                segmentContext.RemainingPath             = nextSegment.Remaining;
                ExternalReview.IsInExternalReviewContext = true;

                return(page);
            }
            catch (ContentNotFoundException)
            {
                return(null);
            }
        }
        public object RoutePartial(IContent content, SegmentContext segmentContext)
        {
            var context = _httpContextAccessor();
            var request = context?.Request;

            if (request != null && request.AcceptTypes.Contains(RoutingConstants.JsonContentType))
            {
                var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);
                if (PropertyExist(content, nextSegment.Next))
                {
                    segmentContext.SetCustomRouteData(RoutingConstants.RoutedPropertyKey, nextSegment.Next);
                    segmentContext.RemainingPath = nextSegment.Remaining;
                    return(content);
                }
            }
            return(null);
        }
Exemplo n.º 19
0
        public object RoutePartial(MediaData content, SegmentContext segmentContext)
        {
            var segment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            int version;

            if (!int.TryParse(segment.Next, out version) || version <= 0)
            {
                return(null);
            }

            segmentContext.RemainingPath = segment.Remaining;

            var list = ContentVersionRepository.Service.List(content.ContentLink);

            return(list.FirstOrDefault(cv => cv.ContentLink.WorkID == version));
        }
        private TaxonomyData GetTaxonomyDataRecursively(SegmentContext segmentContext)
        {
            var contentReference = this.taxonomyRoot;

            var loaderOptions = new LoaderOptions
            {
                LanguageLoaderOption.FallbackWithMaster(CultureInfo.GetCultureInfo(segmentContext.Language))
            };

            TaxonomyData taxonomyData = null;

            while (true)
            {
                var segment = segmentContext.GetNextValue(segmentContext.RemainingPath);

                if (string.IsNullOrEmpty(segment.Next))
                {
                    break;
                }

                var content = this.contentLoader.GetBySegment(contentReference, segment.Next, loaderOptions);

                if (content == null)
                {
                    break;
                }

                contentReference = content.ContentLink;

                if (content is TaxonomyData)
                {
                    taxonomyData = content as TaxonomyData;

                    // Only set remaining path if we found what we were looking for,
                    // otherwise let others try to parse the URL.
                    segmentContext.RemainingPath = segment.Remaining;
                }
            }

            return(taxonomyData);
        }
Exemplo n.º 21
0
        /// <summary>
        /// The route partial.
        /// </summary>
        /// <param name="content">
        /// The content.
        /// </param>
        /// <param name="segmentContext">
        /// The segment context.
        /// </param>
        /// <returns>
        /// The <see cref="object"/>.
        /// </returns>
        public object RoutePartial(PageData content, SegmentContext segmentContext)
        {
            if (segmentContext == null)
            {
                return(content);
            }

            // Use helper method GetNextValue to get the next part from the URL
            SegmentPair nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);

            string output = nextSegment.Next;

            if (string.IsNullOrWhiteSpace(output))
            {
                return(content);
            }

            segmentContext.RemainingPath = nextSegment.Remaining;

            if (output.Equals(OutputConstants.PDF, StringComparison.OrdinalIgnoreCase) && OutputSettings.Instance.EnablePDF)
            {
                OutputHelper.HandlePdf(content);
            }

            if (output.Equals(OutputConstants.Text, StringComparison.OrdinalIgnoreCase) && OutputSettings.Instance.EnableTXT)
            {
                OutputHelper.HandleTxt(content);
            }

            if (output.Equals(OutputConstants.XML, StringComparison.OrdinalIgnoreCase) && OutputSettings.Instance.EnableXML)
            {
                OutputHelper.HandleXml(content);
            }

            if (output.Equals(OutputConstants.JSON, StringComparison.OrdinalIgnoreCase) && OutputSettings.Instance.EnableJSON)
            {
                OutputHelper.HandleJson(content);
            }

            return(content);
        }
        private void AddFacetsToSegmentContext(ConcurrentDictionary <RouteFacetModel, HashSet <object> > routeFacets, SegmentContext segmentContext, RouteFacetModel[] facetNames, string nextSegment, string remaining, RouteFacetModel currentFacet)
        {
            if (String.IsNullOrEmpty(nextSegment))
            {
                return;
            }

            var value = facetNames.FirstOrDefault(x => x.FacetName.Equals(nextSegment, StringComparison.OrdinalIgnoreCase));

            if (value != null)
            {
                currentFacet = value;
            }
            else if (currentFacet != null)
            {
                var facetValue = _facetUrlCreator.GetFacetValue(facetNames, nextSegment);

                routeFacets.AddOrUpdate(currentFacet,
                                        (key) => new HashSet <object> {
                    facetValue
                },
                                        (key, list) =>
                {
                    list.Add(facetValue);
                    return(list);
                });
            }

            segmentContext.RemainingPath = remaining;

            var segmentPair = segmentContext.GetNextValue(segmentContext.RemainingPath);

            nextSegment = _facetUrlCreator.GetFacetValue(facetNames, segmentPair.Next);

            AddFacetsToSegmentContext(routeFacets, segmentContext, facetNames, nextSegment, segmentPair.Remaining, currentFacet);
        }
        private void AddFacetsToSegmentContext(ConcurrentDictionary<RouteFacetModel, HashSet<object>> routeFacets, SegmentContext segmentContext, RouteFacetModel[] facetNames, string nextSegment, string remaining, RouteFacetModel currentFacet)
        {
            if (String.IsNullOrEmpty(nextSegment))
            {
                return;
            }

            var value = facetNames.FirstOrDefault(x => x.FacetName.Equals(nextSegment, StringComparison.OrdinalIgnoreCase));
            if (value != null)
            {
                currentFacet = value;
                
            }
            else if (currentFacet != null)
            {
                var facetValue = _facetUrlCreator.GetFacetValue(facetNames, nextSegment);

                routeFacets.AddOrUpdate(currentFacet,
                   (key) => new HashSet<object> { facetValue },
                   (key, list) =>
                   {
                       list.Add(facetValue);
                       return list;
                   });
            }

            segmentContext.RemainingPath = remaining;

            var segmentPair = segmentContext.GetNextValue(segmentContext.RemainingPath);
            nextSegment = _facetUrlCreator.GetFacetValue(facetNames, segmentPair.Next);

            AddFacetsToSegmentContext(routeFacets, segmentContext, facetNames, nextSegment, segmentPair.Remaining, currentFacet);
        }