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