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