Exemple #1
0
        public void ToString_TemplateRoundtrips(string template)
        {
            var routePattern = RoutePatternFactory.Parse(template);

            var sb = new StringBuilder();

            RoutePatternWriter.WriteString(sb, routePattern.PathSegments);

            Assert.Equal(template, sb.ToString());
        }
        // CreateEndpoints processes the route pattern, replacing area/controller/action parameters with endpoint values
        // Because of default values it is possible for a route pattern to resolve to multiple endpoints
        private int CreateEndpoints(
            List <Endpoint> endpoints,
            ref StringBuilder patternStringBuilder,
            ActionDescriptor action,
            int routeOrder,
            RoutePattern routePattern,
            IReadOnlyDictionary <string, object> allDefaults,
            IReadOnlyDictionary <string, object> nonInlineDefaults,
            string name,
            RouteValueDictionary dataTokens,
            IDictionary <string, IList <IParameterPolicy> > allParameterPolicies,
            bool suppressLinkGeneration,
            bool suppressPathMatching,
            List <Action <EndpointModel> > conventions)
        {
            var newPathSegments           = routePattern.PathSegments.ToList();
            var hasLinkGenerationEndpoint = false;

            // Create a mutable copy
            var nonInlineDefaultsCopy = nonInlineDefaults != null
                ? new RouteValueDictionary(nonInlineDefaults)
                : null;

            var resolvedRouteValues = ResolveActionRouteValues(action, allDefaults);

            for (var i = 0; i < newPathSegments.Count; i++)
            {
                // Check if the pattern can be shortened because the remaining parameters are optional
                //
                // e.g. Matching pattern {controller=Home}/{action=Index} against HomeController.Index
                // can resolve to the following endpoints: (sorted by RouteEndpoint.Order)
                // - /
                // - /Home
                // - /Home/Index
                if (UseDefaultValuePlusRemainingSegmentsOptional(
                        i,
                        action,
                        resolvedRouteValues,
                        allDefaults,
                        ref nonInlineDefaultsCopy,
                        newPathSegments))
                {
                    // The route pattern has matching default values AND an optional parameter
                    // For link generation we need to include an endpoint with parameters and default values
                    // so the link is correctly shortened
                    // e.g. {controller=Home}/{action=Index}/{id=17}
                    if (!hasLinkGenerationEndpoint)
                    {
                        var ep = CreateEndpoint(
                            action,
                            resolvedRouteValues,
                            name,
                            GetPattern(ref patternStringBuilder, newPathSegments),
                            newPathSegments,
                            nonInlineDefaultsCopy,
                            routeOrder++,
                            dataTokens,
                            suppressLinkGeneration,
                            true,
                            conventions);
                        endpoints.Add(ep);

                        hasLinkGenerationEndpoint = true;
                    }

                    var subPathSegments = newPathSegments.Take(i);

                    var subEndpoint = CreateEndpoint(
                        action,
                        resolvedRouteValues,
                        name,
                        GetPattern(ref patternStringBuilder, subPathSegments),
                        subPathSegments,
                        nonInlineDefaultsCopy,
                        routeOrder++,
                        dataTokens,
                        suppressLinkGeneration,
                        suppressPathMatching,
                        conventions);
                    endpoints.Add(subEndpoint);
                }

                UpdatePathSegments(i, action, resolvedRouteValues, routePattern, newPathSegments, ref allParameterPolicies);
            }

            var finalEndpoint = CreateEndpoint(
                action,
                resolvedRouteValues,
                name,
                GetPattern(ref patternStringBuilder, newPathSegments),
                newPathSegments,
                nonInlineDefaultsCopy,
                routeOrder++,
                dataTokens,
                suppressLinkGeneration,
                suppressPathMatching,
                conventions);

            endpoints.Add(finalEndpoint);

            return(routeOrder);

            string GetPattern(ref StringBuilder sb, IEnumerable <RoutePatternPathSegment> segments)
            {
                if (sb == null)
                {
                    sb = new StringBuilder();
                }

                RoutePatternWriter.WriteString(sb, segments);
                var rawPattern = sb.ToString();

                sb.Length = 0;

                return(rawPattern);
            }
        }