Example #1
0
        static IEnumerable GetItems(object node)
        {
            IEnumerable results = null;

            switch (node)
            {
            case IShellController shell:
                results = shell.GetItems();
                break;

            case IShellItemController item:
                results = item.GetItems();
                break;

            case IShellSectionController section:
                results = section.GetItems();
                break;

            case ShellContent content:
                results = Array.Empty <object>();
                break;

            case GlobalRouteItem routeItem:
                results = routeItem.Items;
                break;
            }

            if (results == null)
            {
                throw new ArgumentException($"{node}", nameof(node));
            }

            foreach (var result in results)
            {
                yield return(result);
            }

            if (node is GlobalRouteItem)
            {
                yield break;
            }

            var    keys  = Routing.GetRouteKeys();
            string route = GetRoute(node);

            foreach (var key in keys)
            {
                if (key.StartsWith(_pathSeparator, StringComparison.Ordinal) && !(node is Shell))
                {
                    continue;
                }

                var segments = RetrievePaths(key);

                if (segments[0] == route)
                {
                    yield return(new GlobalRouteItem(key, key));
                }
            }
        }
Example #2
0
        internal static List <RouteRequestBuilder> GenerateRoutePaths(Shell shell, Uri request, Uri originalRequest, bool enableRelativeShellRoutes)
        {
            var routeKeys = Routing.GetRouteKeys();

            for (int i = 0; i < routeKeys.Length; i++)
            {
                routeKeys[i] = FormatUri(routeKeys[i]);
            }

            request         = FormatUri(request, shell);
            originalRequest = FormatUri(originalRequest, shell);

            List <RouteRequestBuilder> possibleRoutePaths = new List <RouteRequestBuilder>();

            if (!request.IsAbsoluteUri)
            {
                request = ConvertToStandardFormat(shell, request);
            }

            string localPath = request.LocalPath;

            bool relativeMatch = false;

            if (!originalRequest.IsAbsoluteUri &&
                !originalRequest.OriginalString.StartsWith("//", StringComparison.Ordinal))
            {
                relativeMatch = true;
            }

            var segments = RetrievePaths(localPath);

            var depthStart = 0;

            if (segments[0] == shell?.Route)
            {
                segments   = segments.Skip(1).ToArray();
                depthStart = 1;
            }
            else
            {
                depthStart = 0;
            }

            if (relativeMatch && shell?.CurrentItem != null)
            {
                var result = ProcessRelativeRoute(shell, routeKeys, segments, enableRelativeShellRoutes, originalRequest);
                if (result.Count > 0)
                {
                    return(result);
                }
            }

            possibleRoutePaths.Clear();
            SearchPath(shell, null, segments, possibleRoutePaths, depthStart);

            var bestMatches = GetBestMatches(possibleRoutePaths);

            if (bestMatches.Count > 0)
            {
                return(bestMatches);
            }

            bestMatches.Clear();
            ExpandOutGlobalRoutes(possibleRoutePaths, routeKeys);

            foreach (var possibleRoutePath in possibleRoutePaths)
            {
                if (possibleRoutePath.IsFullMatch)
                {
                    continue;
                }

                var url = possibleRoutePath.PathFull;

                var globalRouteMatches =
                    SearchForGlobalRoutes(
                        possibleRoutePath.RemainingSegments,
                        new ShellNavigationState(url, false).FullLocation,
                        possibleRoutePath.GetNodeLocation(),
                        routeKeys);

                if (globalRouteMatches.Count != 1)
                {
                    continue;
                }

                var globalRouteMatch = globalRouteMatches[0];

                while (possibleRoutePath.NextSegment != null)
                {
                    var matchIndex = globalRouteMatch.SegmentsMatched.IndexOf(possibleRoutePath.NextSegment);
                    if (matchIndex < 0)
                    {
                        break;
                    }

                    possibleRoutePath.AddGlobalRoute(
                        globalRouteMatch.GlobalRouteMatches[matchIndex],
                        globalRouteMatch.SegmentsMatched[matchIndex]);
                }
            }

            possibleRoutePaths = GetBestMatches(possibleRoutePaths);

            if (possibleRoutePaths.Count == 0)
            {
                foreach (var routeKey in routeKeys)
                {
                    if (routeKey == originalRequest.OriginalString)
                    {
                        var builder = new RouteRequestBuilder(routeKey, routeKey, null, new string[] { routeKey });
                        return(new List <RouteRequestBuilder> {
                            builder
                        });
                    }
                }

                if (!relativeMatch)
                {
                    for (int i = 0; i < routeKeys.Length; i++)
                    {
                        var route = routeKeys[i];
                        var uri   = ConvertToStandardFormat(shell, CreateUri(route));
                        if (uri.Equals(request))
                        {
                            throw new Exception($"Global routes currently cannot be the only page on the stack, so absolute routing to global routes is not supported. For now, just navigate to: {originalRequest.OriginalString.Replace("//", "")}");
                        }
                    }
                }
            }
            return(possibleRoutePaths);
        }