Esempio n. 1
0
        RouteSettings CreateRouteSettings(IEnumerable <ActionInfo> actions)
        {
            if (actions == null)
            {
                throw new ArgumentNullException("actions");
            }

            ActionInfo first     = actions.First();
            string     baseRoute = first.Controller.Register.BaseRoute;

            var controllerMapping = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (string name in actions.Select(a => a.Controller.Name).Distinct(controllerMapping.Comparer))
            {
                controllerMapping.Add(name, actions.First(a => ControllerInfo.NameEquals(a.Controller.Name, name)).Controller.ControllerSegment);
            }

            string controllerCustomRoute = first.Controller.CustomRoute;

            bool includeControllerToken = (controllerCustomRoute != null) ?
                                          first.Controller.CustomRouteHasControllerToken
            : controllerMapping.Count > 1;

            bool controllerFormat          = controllerMapping.Any(p => !String.Equals(p.Key, p.Value, StringComparison.Ordinal));
            bool requiresControllerMapping = controllerFormat && includeControllerToken;

            var segments = new List <string> {
                (includeControllerToken ?
                 first.Controller.UrlTemplate
               : first.Controller.ControllerUrl
                )
            };

            var actionMapping = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (string name in actions.Select(a => a.Name).Distinct(actionMapping.Comparer))
            {
                actionMapping.Add(name, actions.First(a => ActionInfo.NameEquals(a.Name, name)).ActionSegment);
            }

            string actionCustomRoute     = first.CustomRoute;
            bool   allEmptyActionSegment = actionMapping.Values.All(s => s.Length == 0);
            bool   hasEmptyActionSegment = allEmptyActionSegment || actionMapping.Values.Any(s => s.Length == 0);

            bool includeActionToken = (actionCustomRoute != null) ?
                                      first.CustomRouteHasActionToken
            : actionMapping.Count > 1 || first.IsDefaultAction;

            bool actionFormat          = actionMapping.Any(p => !String.Equals(p.Key, p.Value, StringComparison.Ordinal));
            bool requiresActionMapping = actionFormat && includeActionToken;

            if (actionCustomRoute != null)
            {
                if (first.CustomRouteIsAbsolute)
                {
                    actionCustomRoute = actionCustomRoute.Substring(2);

                    segments.Clear();

                    if (baseRoute != null)
                    {
                        segments.AddRange(baseRoute.Split('/'));
                    }
                }

                segments.Add(actionCustomRoute);
            }
            else
            {
                segments.Add(!includeActionToken ? first.ActionSegment : "{action}");
                segments.AddRange(first.RouteParameters.Select(r => r.RouteSegment));
            }

            string url = String.Join("/", segments.Where(s => !String.IsNullOrEmpty(s)));

            var routeSettings = new RouteSettings(url, actions)
            {
                ActionMapping     = (requiresActionMapping) ? actionMapping : null,
                ControllerMapping = (requiresControllerMapping) ? controllerMapping : null,
            };

            if (!includeControllerToken)
            {
                routeSettings.Defaults.Add("controller", controllerMapping.Keys.First());
            }

            ActionInfo defaultAction = (includeActionToken) ?
                                       actions.FirstOrDefault(a => a.IsDefaultAction)
            : first;

            string actionDefault = null;

            if (defaultAction != null)
            {
                actionDefault = (requiresActionMapping) ?
                                defaultAction.ActionSegment
               : defaultAction.Name;
            }
            else if (hasEmptyActionSegment && !allEmptyActionSegment)
            {
                actionDefault = "";
            }

            if (actionDefault != null)
            {
                object actionDef = (actionDefault.Length == 0) ?
                                   (!allEmptyActionSegment) ? this.OptionalParameterValue
               : null
               : actionDefault;

                if (actionDef != null)
                {
                    routeSettings.Defaults.Add("action", actionDef);
                }
            }

            RouteParameterCollection parameters = first.RouteParameters;

            foreach (var param in parameters.Where(p => p.IsOptional))
            {
                routeSettings.Defaults.Add(param.Name, this.OptionalParameterValue);
            }

            if (includeControllerToken)
            {
                routeSettings.Constraints.Add("controller", first.Controller.Provider.CreateSetRouteConstraint(controllerMapping.Values.ToArray()));
            }

            if (includeActionToken)
            {
                routeSettings.Constraints.Add("action", first.Controller.Provider.CreateSetRouteConstraint(actionMapping.Values.Where(s => !String.IsNullOrEmpty(s)).ToArray()));
            }

            var binders = new Dictionary <string, ParameterBinder>(StringComparer.OrdinalIgnoreCase);

            foreach (var param in first.Controller.RouteProperties.Concat(parameters).Where(p => p.Constraint != null || p.Binder != null))
            {
                object routeConstraint;

                if (param.Constraint != null)
                {
                    routeConstraint = first.Controller.Provider.CreateRegexRouteConstraint(param.Constraint, param.ParameterType);
                }
                else
                {
                    routeConstraint = first.Controller.Provider.CreateParameterBindingRouteConstraint(param.Binder);
                }

                if (param.Binder != null)
                {
                    binders[param.Name] = param.Binder;
                }

                routeSettings.Constraints.Add(param.Name, routeConstraint);
            }

            routeSettings.DataTokens[DataTokenKeys.Namespaces] = new string[1] {
                first.Controller.Namespace
            };
            routeSettings.DataTokens[DataTokenKeys.BaseRoute]        = baseRoute;
            routeSettings.DataTokens[DataTokenKeys.RouteContext]     = String.Join("/", first.Controller.CodeRoutingContext);
            routeSettings.DataTokens[DataTokenKeys.ViewsLocation]    = String.Join("/", first.Controller.CodeRoutingContext.Where(s => !s.Contains('{')));
            routeSettings.DataTokens[DataTokenKeys.ParameterBinders] = binders;

            return(routeSettings);
        }