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