示例#1
0
        /// <summary>
        /// Processes one attribute route
        /// </summary>
        /// <param name="action">Action to process</param>
        /// <returns>Route information</returns>
        private AttributeRouteInfo ProcessAttributeRoute(ControllerActionDescriptor action)
        {
            string constraint;

            action.RouteValues.TryGetValue(TreeRouter.RouteGroupKey, out constraint);
            if (string.IsNullOrEmpty(constraint))
            {
                // This can happen if an ActionDescriptor has a route template, but doesn't have one of our
                // special route group constraints. This is a good indication that the user is using a 3rd party
                // routing system, or has customized their ADs in a way that we can no longer understand them.
                //
                // We just treat this case as an 'opt-out' of our attribute routing system.
                return(null);
            }

            var template = TemplateParser.Parse(action.AttributeRouteInfo.Template);

            var info = new AttributeRouteInfo
            {
                Constraints = GetConstraints(action.AttributeRouteInfo.Template, template),
                Defaults    = GetDefaults(action, template),
                Optional    = new List <string>(),
                Order       = action.AttributeRouteInfo.Order,
                Precedence  = RoutePrecedence.ComputeOutbound(template),
            };

            _parser.Parse(template, info);

            return(info);
        }
示例#2
0
        private OutboundRouteEntry CreateOutboundRouteEntry(RouteEndpoint endpoint)
        {
            var routeValuesAddressMetadata = endpoint.Metadata.GetMetadata <IRouteValuesAddressMetadata>();
            var entry = new OutboundRouteEntry()
            {
                Handler            = NullRouter.Instance,
                Order              = endpoint.Order,
                Precedence         = RoutePrecedence.ComputeOutbound(endpoint.RoutePattern),
                RequiredLinkValues = new RouteValueDictionary(routeValuesAddressMetadata?.RequiredValues),
                RouteTemplate      = new RouteTemplate(endpoint.RoutePattern),
                Data      = endpoint,
                RouteName = routeValuesAddressMetadata?.RouteName,
            };

            entry.Defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults);
            return(entry);
        }
示例#3
0
        public void AttributeRoute_GetEntries_CreatesOutboundEntry_WithDefault()
        {
            // Arrange
            var actions = new List <ActionDescriptor>()
            {
                new ActionDescriptor()
                {
                    AttributeRouteInfo = new AttributeRouteInfo()
                    {
                        Template = "api/Blog/{*slug=hello}",
                        Name     = "BLOG_INDEX",
                        Order    = 17,
                    },
                    RouteValues = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                    {
                        { TreeRouter.RouteGroupKey, "1" }
                    },
                    RouteValueDefaults = new Dictionary <string, object>()
                    {
                        { "controller", "Blog" },
                        { "action", "Index" },
                    },
                },
            };

            var builder = CreateBuilder();
            var actionDescriptorProvider = CreateActionDescriptorProvider(actions);
            var route = CreateRoute(CreateHandler().Object, actionDescriptorProvider.Object);

            // Act
            route.AddEntries(builder, actionDescriptorProvider.Object.ActionDescriptors);

            // Assert
            Assert.Collection(
                builder.OutboundEntries,
                e =>
            {
                Assert.Empty(e.Constraints);
                Assert.Equal(new RouteValueDictionary(new { slug = "hello" }), e.Defaults);
                Assert.Equal(RoutePrecedence.ComputeOutbound(e.RouteTemplate), e.Precedence);
                Assert.Equal("BLOG_INDEX", e.RouteName);
                Assert.Equal(17, e.Order);
                Assert.Equal(actions[0].RouteValueDefaults.ToArray(), e.RequiredLinkValues.ToArray());
                Assert.Equal("api/Blog/{*slug=hello}", e.RouteTemplate.TemplateText);
            });
        }
示例#4
0
        /// <summary>
        /// Processes one attribute route
        /// </summary>
        /// <param name="action">Action to process</param>
        /// <returns>Route information</returns>
        private AttributeRouteInfo ProcessAttributeRoute(ControllerActionDescriptor action)
        {
            var template = TemplateParser.Parse(action.AttributeRouteInfo.Template);

            var info = new AttributeRouteInfo
            {
                Constraints = GetConstraints(action.AttributeRouteInfo.Template, template),
                Defaults    = GetDefaults(action, template),
                Optional    = new List <string>(),
                Order       = action.AttributeRouteInfo.Order,
                Precedence  = RoutePrecedence.ComputeOutbound(template),
            };

            _parser.Parse(template, info);

            return(info);
        }
        private OutboundRouteEntry CreateOutboundRouteEntry(
            RouteEndpoint endpoint,
            IReadOnlyDictionary <string, object> requiredValues,
            string routeName)
        {
            var entry = new OutboundRouteEntry()
            {
                Handler            = NullRouter.Instance,
                Order              = endpoint.Order,
                Precedence         = RoutePrecedence.ComputeOutbound(endpoint.RoutePattern),
                RequiredLinkValues = new RouteValueDictionary(requiredValues),
                RouteTemplate      = new RouteTemplate(endpoint.RoutePattern),
                Data      = endpoint,
                RouteName = routeName,
            };

            entry.Defaults = new RouteValueDictionary(endpoint.RoutePattern.Defaults);
            return(entry);
        }
示例#6
0
        internal RoutePattern(
            string rawText,
            Dictionary <string, object> defaults,
            Dictionary <string, IReadOnlyList <RoutePatternConstraintReference> > constraints,
            RoutePatternParameterPart[] parameters,
            RoutePatternPathSegment[] pathSegments)
        {
            Debug.Assert(defaults != null);
            Debug.Assert(constraints != null);
            Debug.Assert(parameters != null);
            Debug.Assert(pathSegments != null);

            RawText      = rawText;
            Defaults     = defaults;
            Constraints  = constraints;
            Parameters   = parameters;
            PathSegments = pathSegments;

            InboundPrecedence  = RoutePrecedence.ComputeInbound(this);
            OutboundPrecedence = RoutePrecedence.ComputeOutbound(this);
        }
示例#7
0
        internal RoutePattern(
            string rawText,
            IReadOnlyDictionary <string, object> defaults,
            IReadOnlyDictionary <string, IReadOnlyList <RoutePatternParameterPolicyReference> > parameterPolicies,
            IReadOnlyList <RoutePatternParameterPart> parameters,
            IReadOnlyList <RoutePatternPathSegment> pathSegments)
        {
            Debug.Assert(defaults != null);
            Debug.Assert(parameterPolicies != null);
            Debug.Assert(parameters != null);
            Debug.Assert(pathSegments != null);

            RawText           = rawText;
            Defaults          = defaults;
            ParameterPolicies = parameterPolicies;
            Parameters        = parameters;
            PathSegments      = pathSegments;

            InboundPrecedence  = RoutePrecedence.ComputeInbound(this);
            OutboundPrecedence = RoutePrecedence.ComputeOutbound(this);
        }
示例#8
0
        private OutboundRouteEntry CreateOutboundRouteEntry(MatcherEndpoint endpoint)
        {
            var routeNameMetadata = endpoint.Metadata.GetMetadata <IRouteNameMetadata>();
            var entry             = new OutboundRouteEntry()
            {
                Handler            = NullRouter.Instance,
                Order              = endpoint.Order,
                Precedence         = RoutePrecedence.ComputeOutbound(endpoint.ParsedTemplate),
                RequiredLinkValues = endpoint.RequiredValues,
                RouteTemplate      = endpoint.ParsedTemplate,
                Data      = endpoint,
                RouteName = routeNameMetadata?.Name,
            };

            // TODO: review. These route constriants should be constructed when the endpoint
            // is built. This way they can be checked for validity on app startup too
            var constraintBuilder = new RouteConstraintBuilder(
                _inlineConstraintResolver,
                endpoint.ParsedTemplate.TemplateText);

            foreach (var parameter in endpoint.ParsedTemplate.Parameters)
            {
                if (parameter.InlineConstraints != null)
                {
                    if (parameter.IsOptional)
                    {
                        constraintBuilder.SetOptional(parameter.Name);
                    }

                    foreach (var constraint in parameter.InlineConstraints)
                    {
                        constraintBuilder.AddResolvedConstraint(parameter.Name, constraint.Constraint);
                    }
                }
            }
            entry.Constraints = constraintBuilder.Build();
            entry.Defaults    = endpoint.Defaults;
            return(entry);
        }
示例#9
0
        /// <summary>
        /// Adds a new outbound route to the <see cref="TreeRouter"/>.
        /// </summary>
        /// <param name="handler">The <see cref="IRouter"/> for handling the link generation.</param>
        /// <param name="routeTemplate">The <see cref="RouteTemplate"/> of the route.</param>
        /// <param name="requiredLinkValues">The <see cref="RouteValueDictionary"/> containing the route values.</param>
        /// <param name="routeName">The route name.</param>
        /// <param name="order">The route order.</param>
        /// <returns>The <see cref="OutboundRouteEntry"/>.</returns>
        public OutboundRouteEntry MapOutbound(
            IRouter handler,
            RouteTemplate routeTemplate,
            RouteValueDictionary requiredLinkValues,
            string routeName,
            int order)
        {
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            if (routeTemplate == null)
            {
                throw new ArgumentNullException(nameof(routeTemplate));
            }

            if (requiredLinkValues == null)
            {
                throw new ArgumentNullException(nameof(requiredLinkValues));
            }

            var entry = new OutboundRouteEntry()
            {
                Handler            = handler,
                Order              = order,
                Precedence         = RoutePrecedence.ComputeOutbound(routeTemplate),
                RequiredLinkValues = requiredLinkValues,
                RouteName          = routeName,
                RouteTemplate      = routeTemplate,
            };

            var constraintBuilder = new RouteConstraintBuilder(_constraintResolver, routeTemplate.TemplateText);

            foreach (var parameter in routeTemplate.Parameters)
            {
                if (parameter.InlineConstraints != null)
                {
                    if (parameter.IsOptional)
                    {
                        constraintBuilder.SetOptional(parameter.Name);
                    }

                    foreach (var constraint in parameter.InlineConstraints)
                    {
                        constraintBuilder.AddResolvedConstraint(parameter.Name, constraint.Constraint);
                    }
                }
            }

            entry.Constraints = constraintBuilder.Build();

            entry.Defaults = new RouteValueDictionary();
            foreach (var parameter in entry.RouteTemplate.Parameters)
            {
                if (parameter.DefaultValue != null)
                {
                    entry.Defaults.Add(parameter.Name, parameter.DefaultValue);
                }
            }

            OutboundEntries.Add(entry);
            return(entry);
        }