예제 #1
0
        public void AttributeRoute_GetEntries_CreatesLinkGenerationEntry_WithDefault()
        {
            // Arrange
            var actions = new List <ActionDescriptor>()
            {
                new ActionDescriptor()
                {
                    AttributeRouteInfo = new AttributeRouteInfo()
                    {
                        Template = "api/Blog/{*slug=hello}",
                        Name     = "BLOG_INDEX",
                        Order    = 17,
                    },
                    RouteConstraints = new List <RouteDataActionConstraint>()
                    {
                        new RouteDataActionConstraint(TreeRouter.RouteGroupKey, "1"),
                    },
                    RouteValueDefaults = new Dictionary <string, object>()
                    {
                        { "controller", "Blog" },
                        { "action", "Index" },
                    },
                },
            };

            var actionDescriptorProvider = CreateActionDescriptorProvider(actions);

            var route = CreateRoute(CreateHandler().Object, actionDescriptorProvider.Object);

            // Act
            var entries = route.GetEntries(actionDescriptorProvider.Object.ActionDescriptors);

            // Assert
            Assert.Collection(
                entries.LinkGenerationEntries,
                e =>
            {
                Assert.NotNull(e.Binder);
                Assert.Empty(e.Constraints);
                Assert.Equal(new RouteValueDictionary(new { slug = "hello" }), e.Defaults);
                Assert.Equal(RoutePrecedence.ComputeGenerated(e.Template), e.GenerationPrecedence);
                Assert.Equal("BLOG_INDEX", e.Name);
                Assert.Equal(17, e.Order);
                Assert.Equal(actions[0].RouteValueDefaults, e.RequiredLinkValues);
                Assert.Equal("1", e.RouteGroup);
                Assert.Equal("api/Blog/{*slug=hello}", e.Template.TemplateText);
            });
        }
예제 #2
0
        private static RouteInfo GetRouteInfo(
            IInlineConstraintResolver constraintResolver,
            Dictionary <string, RouteTemplate> templateCache,
            ActionDescriptor action)
        {
            var constraint = action.RouteConstraints
                             .FirstOrDefault(c => c.RouteKey == TreeRouter.RouteGroupKey);

            if (constraint == null ||
                constraint.KeyHandling != RouteKeyHandling.RequireKey ||
                constraint.RouteValue == null)
            {
                // 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 routeInfo = new RouteInfo()
            {
                ActionDescriptor = action,
                RouteGroup       = constraint.RouteValue,
                RouteTemplate    = action.AttributeRouteInfo.Template,
            };

            try
            {
                RouteTemplate parsedTemplate;
                if (!templateCache.TryGetValue(action.AttributeRouteInfo.Template, out parsedTemplate))
                {
                    // Parsing with throw if the template is invalid.
                    parsedTemplate = TemplateParser.Parse(action.AttributeRouteInfo.Template);
                    templateCache.Add(action.AttributeRouteInfo.Template, parsedTemplate);
                }

                routeInfo.ParsedTemplate = parsedTemplate;
            }
            catch (Exception ex)
            {
                routeInfo.ErrorMessage = ex.Message;
                return(routeInfo);
            }

            foreach (var kvp in action.RouteValueDefaults)
            {
                foreach (var parameter in routeInfo.ParsedTemplate.Parameters)
                {
                    if (string.Equals(kvp.Key, parameter.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        routeInfo.ErrorMessage = Resources.FormatAttributeRoute_CannotContainParameter(
                            routeInfo.RouteTemplate,
                            kvp.Key,
                            kvp.Value);

                        return(routeInfo);
                    }
                }
            }

            routeInfo.Order = action.AttributeRouteInfo.Order;

            routeInfo.MatchPrecedence      = RoutePrecedence.ComputeMatched(routeInfo.ParsedTemplate);
            routeInfo.GenerationPrecedence = RoutePrecedence.ComputeGenerated(routeInfo.ParsedTemplate);

            routeInfo.Name = action.AttributeRouteInfo.Name;

            var constraintBuilder = new RouteConstraintBuilder(constraintResolver, routeInfo.RouteTemplate);

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

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

            routeInfo.Constraints = constraintBuilder.Build();

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

            return(routeInfo);
        }