/// <summary>
        /// Maps the attribute-defined routes for the application.
        /// </summary>
        /// <param name="routes"></param>
        /// <param name="controllerTypes">The controller types to scan.</param>
        /// <param name="constraintResolver">
        /// The <see cref="IInlineConstraintResolver"/> to use for resolving inline constraints in route templates.
        /// </param>
        public static void MapAttributeRoutes(RouteCollection routes, IEnumerable<Type> controllerTypes,
            IInlineConstraintResolver constraintResolver)
        {
            SubRouteCollection subRoutes = new SubRouteCollection();
            AddRouteEntries(subRoutes, controllerTypes, constraintResolver);
            IReadOnlyCollection<RouteEntry> entries = subRoutes.Entries;

            if (entries.Count > 0)
            {
                RouteCollectionRoute aggregrateRoute = new RouteCollectionRoute(subRoutes);
                routes.Add(aggregrateRoute);

                // This sort is here to enforce a static ordering for link generation using these routes. 
                // We don't apply dynamic criteria like ActionSelectors on link generation, but we can use the static
                // ones.
                //
                // Routes to actions are placed first because they are considered more specific. A route to an action
                // will only match for link generation if the action name was supplied, so this is essential for
                // correctness. Without this a controller-level route could be 'greedy' and generate a link when
                // the action-level route was intended.
                RouteEntry[] sorted = entries
                    .OrderBy(r => r.Route.GetOrder())
                    .ThenBy(r => r.Route.GetTargetIsAction() ? 0 : 1)
                    .ThenBy(r => r.Route.GetPrecedence())
                    .ToArray();

                AddGenerationHooksForSubRoutes(routes, sorted);
            }
        }
        /// <summary>
        /// Maps the attribute-defined routes for the application.
        /// </summary>
        /// <param name="routes"></param>
        /// <param name="controllerTypes">The controller types to scan.</param>
        /// <param name="constraintResolver">
        /// The <see cref="IInlineConstraintResolver"/> to use for resolving inline constraints in route templates.
        /// </param>
        public static void MapAttributeRoutes(RouteCollection routes, IEnumerable <Type> controllerTypes,
                                              IInlineConstraintResolver constraintResolver)
        {
            AttributeRoutingMapper mapper = new AttributeRoutingMapper(new RouteBuilder2(constraintResolver));

            SubRouteCollection subRoutes = new SubRouteCollection();

            mapper.AddRouteEntries(subRoutes, controllerTypes);
            IReadOnlyCollection <RouteEntry> entries = subRoutes.Entries;

            if (entries.Count > 0)
            {
                RouteCollectionRoute aggregrateRoute = new RouteCollectionRoute(subRoutes);
                routes.Add(aggregrateRoute);

                // This sort is here to enforce a static ordering for link generation using these routes.
                // We don't apply dynamic criteria like ActionSelectors on link generation, but we can use the static
                // ones.
                RouteEntry[] sorted = entries
                                      .OrderBy(r => r.Route.GetOrder())
                                      .ThenBy(r => r.Route.GetPrecedence())
                                      .ToArray();

                AddGenerationHooksForSubRoutes(routes, sorted);
            }
        }
 internal static IReadOnlyCollection<RouteEntry> MapAttributeRoutes(
     ReflectedAsyncControllerDescriptor controller)
 {
     SubRouteCollection collector = new SubRouteCollection();
     AddRouteEntries(collector, controller, new DefaultInlineConstraintResolver());
     return collector.Entries;
 }
        internal IReadOnlyCollection <RouteEntry> MapAttributeRoutes(ReflectedAsyncControllerDescriptor controller)
        {
            SubRouteCollection collector = new SubRouteCollection();

            AddRouteEntries(collector, controller);
            return(collector.Entries);
        }
示例#5
0
        internal static void AddRouteEntries(SubRouteCollection collector, IEnumerable <Type> controllerTypes,
                                             IInlineConstraintResolver constraintResolver, IDirectRouteProvider directRouteProvider)
        {
            IEnumerable <ReflectedAsyncControllerDescriptor> controllers = GetControllerDescriptors(controllerTypes);

            foreach (ReflectedAsyncControllerDescriptor controller in controllers)
            {
                List <ActionDescriptor> actions = GetActionDescriptors(controller);

                IReadOnlyCollection <RouteEntry> entries = directRouteProvider.GetDirectRoutes(controller, actions, constraintResolver);
                if (entries == null)
                {
                    throw Error.InvalidOperation(
                              MvcResources.TypeMethodMustNotReturnNull,
                              typeof(IDirectRouteProvider).Name,
                              "GetDirectRoutes");
                }

                foreach (RouteEntry entry in entries)
                {
                    if (entry == null)
                    {
                        throw Error.InvalidOperation(
                                  MvcResources.TypeMethodMustNotReturnNull,
                                  typeof(IDirectRouteProvider).Name,
                                  "GetDirectRoutes");
                    }

                    DirectRouteBuilder.ValidateRouteEntry(entry);

                    // This marks the action/controller as unreachable via traditional routing.
                    if (entry.Route.GetTargetIsAction())
                    {
                        var actionDescriptors = entry.Route.GetTargetActionDescriptors();
                        Contract.Assert(actionDescriptors != null && actionDescriptors.Any());

                        foreach (var actionDescriptor in actionDescriptors.OfType <IMethodInfoActionDescriptor>())
                        {
                            var methodInfo = actionDescriptor.MethodInfo;
                            if (methodInfo != null)
                            {
                                controller.Selector.StandardRouteMethods.Remove(methodInfo);
                            }
                        }
                    }
                    else
                    {
                        // This is a controller-level route - no actions in this controller are reachable via
                        // traditional routes.
                        controller.Selector.StandardRouteMethods.Clear();
                    }
                }

                collector.AddRange(entries);
            }
        }
 private static void AddRouteEntries(SubRouteCollection collector, string areaPrefix, string prefix,
     IEnumerable<IDirectRouteFactory> factories, IReadOnlyCollection<ActionDescriptor> actions,
     IInlineConstraintResolver constraintResolver, bool targetIsAction)
 {
     foreach (IDirectRouteFactory factory in factories)
     {
         RouteEntry entry = CreateRouteEntry(areaPrefix, prefix, factory, actions, constraintResolver,
             targetIsAction);
         collector.Add(entry);
     }
 }
 private void AddRouteEntries(SubRouteCollection collector, string areaPrefix, string prefix,
                              IEnumerable <IRouteInfoProvider> providers, ControllerDescriptor controller,
                              IList <ActionDescriptor> actions, bool routeIsForAction)
 {
     foreach (IRouteInfoProvider provider in providers)
     {
         RouteEntry entry = CreateRouteEntry(areaPrefix, prefix, provider, controller, actions,
                                             routeIsForAction);
         collector.Add(entry);
     }
 }
示例#8
0
        // just for testing
        internal static IReadOnlyCollection <RouteEntry> GetAttributeRoutes(Type controllerType)
        {
            SubRouteCollection collector = new SubRouteCollection();

            AddRouteEntries(
                collector,
                new Type[] { controllerType },
                new DefaultInlineConstraintResolver(),
                new DefaultDirectRouteProvider());

            return(collector.Entries);
        }
        internal void AddRouteEntries(SubRouteCollection collector, IEnumerable <Type> controllerTypes)
        {
            ControllerDescriptorCache descriptorsCache = new AsyncControllerActionInvoker().DescriptorCache;
            IEnumerable <ReflectedAsyncControllerDescriptor> descriptors = controllerTypes
                                                                           .Select(
                type =>
                descriptorsCache.GetDescriptor(type, innerType => new ReflectedAsyncControllerDescriptor(innerType), type))
                                                                           .Cast <ReflectedAsyncControllerDescriptor>();

            foreach (ReflectedAsyncControllerDescriptor controllerDescriptor in descriptors)
            {
                AddRouteEntries(collector, controllerDescriptor);
            }
        }
        internal static void AddRouteEntries(SubRouteCollection collector,
            ReflectedAsyncControllerDescriptor controller, IInlineConstraintResolver constraintResolver)
        {
            string prefix = GetRoutePrefix(controller);

            RouteAreaAttribute area = controller.GetAreaFrom();
            string areaName = controller.GetAreaName(area);
            string areaPrefix = area != null ? area.AreaPrefix ?? area.AreaName : null;
            ValidateAreaPrefixTemplate(areaPrefix, areaName, controller);

            AsyncActionMethodSelector actionSelector = controller.Selector;

            foreach (var method in actionSelector.DirectRouteMethods)
            {
                ActionDescriptor action = CreateActionDescriptor(controller, actionSelector, method);

                IEnumerable<IDirectRouteFactory> factories = GetRouteFactories(method, controller.ControllerType);

                AddRouteEntries(collector, areaPrefix, prefix, factories, new ActionDescriptor[] { action },
                    constraintResolver, targetIsAction: true);
            }

            // Check for controller-level routes. 
            List<ActionDescriptor> actionsWithoutRoutes = new List<ActionDescriptor>();

            foreach (var method in actionSelector.StandardRouteMethods)
            {
                ActionDescriptor action = CreateActionDescriptor(controller, actionSelector, method);

                actionsWithoutRoutes.Add(action);
            }

            IReadOnlyCollection<IDirectRouteFactory> controllerFactories = GetRouteFactories(controller);

            // If they exist and have not been overridden, create routes for controller-level route providers.
            if (controllerFactories.Count > 0 && actionsWithoutRoutes.Count > 0)
            {
                AddRouteEntries(collector, areaPrefix, prefix, controllerFactories, actionsWithoutRoutes,
                    constraintResolver, targetIsAction: false);
            }
        }
示例#11
0
        public void SubRouteCollection_Throws_OnDuplicateNamedRoute()
        {
            // Arrange
            var collection = new SubRouteCollection();
            var route1     = new Route("Home/Index", new Mock <IRouteHandler>().Object);
            var route2     = new Route("Person/Index", new Mock <IRouteHandler>().Object);

            collection.Add(new RouteEntry {
                Name = "route", Route = route1
            });

            var expectedError =
                "A route named 'route' is already in the route collection. Route names must be unique." + Environment.NewLine +
                Environment.NewLine +
                "Duplicates:" + Environment.NewLine +
                "Person/Index" + Environment.NewLine +
                "Home/Index";

            // Act & Assert
            Assert.Throws <InvalidOperationException>(() => collection.Add(new RouteEntry {
                Name = "route", Route = route2
            }), expectedError);
        }
 public RouteCollectionRoute()
 {
     SubRoutes = new SubRouteCollection();
 }