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