Beispiel #1
0
        private void UpdatePathSegments(
            int i,
            ActionDescriptor action,
            IDictionary <string, string> resolvedRequiredValues,
            RoutePattern routePattern,
            List <RoutePatternPathSegment> newPathSegments,
            ref IDictionary <string, IList <IParameterPolicy> > allParameterPolicies)
        {
            List <RoutePatternPart> segmentParts = null; // Initialize only as needed
            var segment = newPathSegments[i];

            for (var j = 0; j < segment.Parts.Count; j++)
            {
                var part = segment.Parts[j];

                if (part is RoutePatternParameterPart parameterPart)
                {
                    if (resolvedRequiredValues.TryGetValue(parameterPart.Name, out var parameterRouteValue))
                    {
                        if (segmentParts == null)
                        {
                            segmentParts = segment.Parts.ToList();
                        }
                        if (allParameterPolicies == null)
                        {
                            allParameterPolicies = MvcEndpointInfo.BuildParameterPolicies(routePattern.Parameters, _parameterPolicyFactory);
                        }

                        // Route value could be null if it is a "known" route value.
                        // Do not use the null value to de-normalize the route pattern,
                        // instead leave the parameter unchanged.
                        // e.g.
                        //     RouteValues will contain a null "page" value if there are Razor pages
                        //     Skip replacing the {page} parameter
                        if (parameterRouteValue != null)
                        {
                            if (allParameterPolicies.TryGetValue(parameterPart.Name, out var parameterPolicies))
                            {
                                // Check if the parameter has a transformer policy
                                // Use the first transformer policy
                                for (var k = 0; k < parameterPolicies.Count; k++)
                                {
                                    if (parameterPolicies[k] is IOutboundParameterTransformer parameterTransformer)
                                    {
                                        parameterRouteValue = parameterTransformer.TransformOutbound(parameterRouteValue);
                                        break;
                                    }
                                }
                            }

                            segmentParts[j] = RoutePatternFactory.LiteralPart(parameterRouteValue);
                        }
                    }
                }
            }

            // A parameter part was replaced so replace segment with updated parts
            if (segmentParts != null)
            {
                newPathSegments[i] = RoutePatternFactory.Segment(segmentParts);
            }
        }
Beispiel #2
0
        // 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)
        {
            var newPathSegments = routePattern.PathSegments.ToList();

            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}/{id?} against HomeController.Index
                // can resolve to the following endpoints:
                // - /Home/Index/{id?}
                // - /Home
                // - /
                if (UseDefaultValuePlusRemainingSegmentsOptional(i, action, allDefaults, newPathSegments))
                {
                    var subPathSegments = newPathSegments.Take(i);

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

                List <RoutePatternPart> segmentParts = null; // Initialize only as needed
                var segment = newPathSegments[i];
                for (var j = 0; j < segment.Parts.Count; j++)
                {
                    var part = segment.Parts[j];

                    if (part.IsParameter &&
                        part is RoutePatternParameterPart parameterPart &&
                        action.RouteValues.ContainsKey(parameterPart.Name))
                    {
                        if (segmentParts == null)
                        {
                            segmentParts = segment.Parts.ToList();
                        }
                        if (allParameterPolicies == null)
                        {
                            allParameterPolicies = MvcEndpointInfo.BuildParameterPolicies(routePattern.Parameters, _parameterPolicyFactory);
                        }

                        var parameterRouteValue = action.RouteValues[parameterPart.Name];

                        // Replace parameter with literal value
                        if (allParameterPolicies.TryGetValue(parameterPart.Name, out var parameterPolicies))
                        {
                            // Check if the parameter has a transformer policy
                            // Use the first transformer policy
                            for (var k = 0; k < parameterPolicies.Count; k++)
                            {
                                if (parameterPolicies[k] is IParameterTransformer parameterTransformer)
                                {
                                    parameterRouteValue = parameterTransformer.Transform(parameterRouteValue);
                                    break;
                                }
                            }
                        }

                        segmentParts[j] = RoutePatternFactory.LiteralPart(parameterRouteValue);
                    }
                }

                // A parameter part was replaced so replace segment with updated parts
                if (segmentParts != null)
                {
                    newPathSegments[i] = RoutePatternFactory.Segment(segmentParts);
                }
            }

            var endpoint = CreateEndpoint(
                action,
                name,
                GetPattern(ref patternStringBuilder, newPathSegments),
                newPathSegments,
                nonInlineDefaults,
                routeOrder++,
                dataTokens,
                suppressLinkGeneration,
                suppressPathMatching);

            endpoints.Add(endpoint);

            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);
            }
        }