internal List <RouteEntry> MapMvcAttributeRoutes(ReflectedAsyncControllerDescriptor controllerDescriptor)
        {
            RoutePrefixAttribute prefixAttribute = GetPrefixFrom(controllerDescriptor);

            ValidatePrefixTemplate(prefixAttribute, controllerDescriptor);

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

            ValidateAreaPrefixTemplate(areaPrefix, areaName, controllerDescriptor);

            string controllerName = controllerDescriptor.ControllerName;

            AsyncActionMethodSelector actionSelector    = controllerDescriptor.Selector;
            IEnumerable <MethodInfo>  actionMethodsInfo = actionSelector.AliasedMethods
                                                          .Concat(actionSelector.NonAliasedMethods.SelectMany(x => x))
                                                          .Where(m => m.DeclaringType == controllerDescriptor.ControllerType);

            if (actionSelector.AllowLegacyAsyncActions)
            {
                // if the ActionAsync / ActionCompleted pattern is used, we need to remove the "Completed" methods
                // and not look up routing attributes on them
                actionMethodsInfo =
                    actionMethodsInfo.Where(m => !m.Name.EndsWith("Completed", StringComparison.OrdinalIgnoreCase));
            }

            List <RouteEntry> routeEntries = new List <RouteEntry>();

            foreach (var method in actionMethodsInfo)
            {
                string actionName = GetCanonicalActionName(method, actionSelector.AllowLegacyAsyncActions);
                IEnumerable <IDirectRouteInfoProvider> routeAttributes = GetRouteAttributes(method);

                foreach (var routeAttribute in routeAttributes)
                {
                    ValidateTemplate(routeAttribute, actionName, controllerDescriptor);

                    string prefix = prefixAttribute != null ? prefixAttribute.Prefix : null;

                    string template = CombinePrefixAndAreaWithTemplate(areaPrefix, prefix, routeAttribute.RouteTemplate);
                    Route  route    = _routeBuilder.BuildDirectRoute(template, routeAttribute.Verbs, controllerName,
                                                                     actionName, method, areaName);
                    RouteEntry entry = new RouteEntry
                    {
                        Name          = routeAttribute.RouteName ?? template,
                        Route         = route,
                        RouteTemplate = template,
                        ParsedRoute   = RouteParser.Parse(route.Url),
                        Order         = routeAttribute.RouteOrder
                    };
                    routeEntries.Add(entry);
                }
            }

            return(routeEntries);
        }
        /// <summary>
        /// Builds an <see cref="Route"/> for a particular controller.
        /// </summary>
        /// <param name="routeTemplate">The tokenized route template for the route.</param>
        /// <param name="routeInfoProvider">The info provider for the route.</param>
        /// <param name="controllerDescriptor">The controller the route attribute has been applied on.</param>
        /// <param name="actionDescriptors">The actions reachable by this route.</param>
        /// <param name="routeIsForAction">Whether or not the direct route is for an action.</param>
        /// <returns>The generated <see cref="Route"/>.</returns>
        public Route BuildDirectRoute(
            string routeTemplate,
            IRouteInfoProvider routeInfoProvider,
            ControllerDescriptor controllerDescriptor,
            IEnumerable <ActionDescriptor> actionDescriptors,
            bool routeIsForAction)
        {
            if (routeTemplate == null)
            {
                throw Error.ArgumentNull("routeTemplate");
            }

            if (routeInfoProvider == null)
            {
                throw Error.ArgumentNull("routeInfoProvider");
            }

            if (controllerDescriptor == null)
            {
                throw Error.ArgumentNull("controllerDescriptor");
            }

            if (actionDescriptors == null || !actionDescriptors.Any())
            {
                throw Error.ParameterCannotBeNullOrEmpty("actionDescriptors");
            }

            string controllerName = controllerDescriptor.ControllerName;

            RouteAreaAttribute area     = controllerDescriptor.GetAreaFrom();
            string             areaName = controllerDescriptor.GetAreaName(area);

            RouteValueDictionary defaults = new RouteValueDictionary
            {
                { "controller", controllerName }
            };

            if (routeIsForAction)
            {
                ActionDescriptor actionDescriptor = actionDescriptors.Single();
                defaults.Add("action", actionDescriptor.ActionName);
            }

            RouteValueDictionary constraints = new RouteValueDictionary();

            string      detokenizedRouteTemplate = InlineRouteTemplateParser.ParseRouteTemplate(routeTemplate, defaults, constraints, ConstraintResolver);
            ParsedRoute parsedRoute = RouteParser.Parse(detokenizedRouteTemplate);

            RouteValueDictionary dataTokens = new RouteValueDictionary();

            dataTokens[RouteDataTokenKeys.DirectRoutePrecedence] = RoutePrecedence.Compute(parsedRoute, constraints);
            dataTokens[RouteDataTokenKeys.DirectRouteController] = controllerDescriptor;
            dataTokens[RouteDataTokenKeys.DirectRouteActions]    = actionDescriptors;

            int order = 0;
            IOrderedRouteInfoProvider orderedAttribute = routeInfoProvider as IOrderedRouteInfoProvider;

            if (orderedAttribute != null)
            {
                order = orderedAttribute.Order;
            }

            dataTokens[RouteDataTokenKeys.DirectRouteOrder] = order;

            if (areaName != null)
            {
                dataTokens.Add(RouteDataTokenKeys.Area, areaName);
                dataTokens.Add(RouteDataTokenKeys.UseNamespaceFallback, value: false);

                Type controllerType = controllerDescriptor.ControllerType;
                if (controllerType != null)
                {
                    dataTokens.Add(RouteDataTokenKeys.Namespaces, new[] { controllerType.Namespace });
                }
            }

            Route route = new Route(detokenizedRouteTemplate, new MvcRouteHandler())
            {
                Defaults    = defaults,
                Constraints = constraints,
                DataTokens  = dataTokens
            };

            return(route);
        }
Beispiel #3
0
        internal List <RouteEntry> MapMvcAttributeRoutes(ReflectedAsyncControllerDescriptor controllerDescriptor)
        {
            string prefix = controllerDescriptor.GetPrefixFrom();

            ValidatePrefixTemplate(prefix, controllerDescriptor);

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

            ValidateAreaPrefixTemplate(areaPrefix, areaName, controllerDescriptor);

            string controllerName = controllerDescriptor.ControllerName;

            AsyncActionMethodSelector actionSelector    = controllerDescriptor.Selector;
            IEnumerable <MethodInfo>  actionMethodsInfo = actionSelector.DirectRouteMethods;

            List <RouteEntry> routeEntries = new List <RouteEntry>();

            foreach (var method in actionMethodsInfo)
            {
                string actionName = actionSelector.GetActionName(method);
                IEnumerable <IRouteInfoProvider> routeAttributes = GetRouteAttributes(method, controllerDescriptor.ControllerType);

                IEnumerable <string> verbs = GetActionVerbs(method);

                foreach (var routeAttribute in routeAttributes)
                {
                    ValidateTemplate(routeAttribute.Template, actionName, controllerDescriptor);

                    string template = CombinePrefixAndAreaWithTemplate(areaPrefix, prefix, routeAttribute.Template);
                    Route  route    = _routeBuilder.BuildDirectRoute(template, verbs, controllerName,
                                                                     actionName, method, areaName);
                    RouteEntry entry = new RouteEntry
                    {
                        Name        = routeAttribute.Name,
                        Route       = route,
                        Template    = template,
                        ParsedRoute = RouteParser.Parse(route.Url),
                        HasVerbs    = verbs.Any()
                    };
                    routeEntries.Add(entry);
                }
            }

            // Check for controller-level routes.
            IEnumerable <IRouteInfoProvider> controllerRouteAttributes = controllerDescriptor.GetDirectRoutes();

            foreach (var routeAttribute in controllerRouteAttributes)
            {
                string template = CombinePrefixAndAreaWithTemplate(areaPrefix, prefix, routeAttribute.Template);

                Route      route = _routeBuilder.BuildDirectRoute(template, controllerDescriptor);
                RouteEntry entry = new RouteEntry
                {
                    Name        = routeAttribute.Name,
                    Route       = route,
                    Template    = template,
                    ParsedRoute = RouteParser.Parse(route.Url)
                };
                routeEntries.Add(entry);
            }

            return(routeEntries);
        }