private RouteValueDictionary CreateRouteConstraints(RouteSpecification routeSpec)
        {
            var constraints = new RouteValueDictionary();

            // Default constraints
            constraints.Add("httpMethod", new RestfulHttpMethodConstraint(routeSpec.HttpMethods));

            // Attribute-based constraints
            foreach (var constraintAttribute in routeSpec.ConstraintAttributes.Where(c => !constraints.ContainsKey(c.Key)))
            {
                constraints.Add(constraintAttribute.Key, constraintAttribute.Constraint);
            }

            var detokenizedUrl    = DetokenizeUrl(CreateRouteUrl(routeSpec));
            var urlParameterNames = GetUrlParameterNames(detokenizedUrl);

            // Convention-based constraints
            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;
                var matchedUrlParameterNames = urlParameterNames.Where(n => Regex.IsMatch(n, pattern));
                foreach (var urlParameterName in matchedUrlParameterNames.Where(n => !constraints.ContainsKey(n)))
                {
                    constraints.Add(urlParameterName, defaultConstraint.Value);
                }
            }

            return(constraints);
        }
Exemplo n.º 2
0
        private RouteValueDictionary CreateRouteConstraints(RouteSpecification routeSpec)
        {
            var constraints = new RouteValueDictionary();

            // Default constraints
            constraints.Add("httpMethod", new RestfulHttpMethodConstraint(routeSpec.HttpMethod));

            // Attribute-based constraints
            foreach (var constraintAttribute in routeSpec.ConstraintAttributes.Where(c => !constraints.ContainsKey(c.Key)))
                constraints.Add(constraintAttribute.Key, constraintAttribute.Constraint);

            var detokenizedUrl = DetokenizeUrl(CreateRouteUrl(routeSpec));
            var urlParameterNames = GetUrlParameterNames(detokenizedUrl);

            // Convention-based constraints
            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;
                var matchedUrlParameterNames = urlParameterNames.Where(n => Regex.IsMatch(n, pattern));
                foreach (var urlParameterName in matchedUrlParameterNames.Where(n => !constraints.ContainsKey(n)))
                    constraints.Add(urlParameterName, defaultConstraint.Value);
            }

            return constraints;
        }
Exemplo n.º 3
0
        private IEnumerable<AttributeRoute> Build(RouteSpecification routeSpec)
        {
            var route = new AttributeRoute(CreateRouteUrl(routeSpec),
                                           CreateRouteDefaults(routeSpec),
                                           CreateRouteConstraints(routeSpec),
                                           CreateRouteDataTokens(routeSpec),
                                           _configuration)
            {
                RouteName = CreateRouteName(routeSpec),
                Translations = CreateRouteTranslations(routeSpec),
                Subdomain = routeSpec.Subdomain
            };

            // Yield the default route first
            yield return route;

            // Then yield the translations
            if (route.Translations == null)
                yield break;

            foreach (var translation in route.Translations)
            {
                // Backreference the default route.
                translation.DefaultRoute = route;

                yield return translation;
            }
        }
        private RouteValueDictionary CreateRouteDefaults(RouteSpecification routeSpec)
        {
            var defaults = new RouteValueDictionary
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };

            foreach (var defaultAttribute in routeSpec.DefaultAttributes.Where(d => !defaults.ContainsKey(d.Key)))
            {
                defaults.Add(defaultAttribute.Key, defaultAttribute.Value);
            }

            // Inspect the url for optional parameters, specified with a leading ?
            var optionalParameterDefaults =
                from parameter in GetUrlParameterContents(routeSpec.Url)
                where parameter.StartsWith("?")
                let parameterName = parameter.TrimStart('?')
                                    select new RouteDefaultAttribute(parameterName, UrlParameter.Optional);

            foreach (var defautAttribute in optionalParameterDefaults.Where(d => !defaults.ContainsKey(d.Key)))
            {
                defaults.Add(defautAttribute.Key, defautAttribute.Value);
            }

            return(defaults);
        }
Exemplo n.º 5
0
        private IEnumerable <IAttributeRoute> CreateRouteTranslations(RouteSpecification routeSpec)
        {
            // If no translation provider, then get out of here.
            if (!_configuration.TranslationProviders.Any())
            {
                yield break;
            }

            // Merge all the culture names from the various providers.
            var cultureNames = _configuration.GetTranslationProviderCultureNames();

            // Built the route translations,
            // choosing the first available translated route component from among the providers
            foreach (var cultureName in cultureNames)
            {
                string translatedRouteUrl      = null,
                         translatedRoutePrefix = null,
                         translatedAreaUrl     = null;

                foreach (var provider in _configuration.TranslationProviders)
                {
                    translatedRouteUrl    = translatedRouteUrl ?? provider.TranslateRouteUrl(cultureName, routeSpec);
                    translatedRoutePrefix = translatedRoutePrefix ?? provider.TranslateRoutePrefix(cultureName, routeSpec);
                    translatedAreaUrl     = translatedAreaUrl ?? provider.TranslateAreaUrl(cultureName, routeSpec);
                }

                // If nothing is translated, then bail.
                if (translatedRouteUrl == null && translatedRoutePrefix == null && translatedAreaUrl == null)
                {
                    continue;
                }

                //*********************************************
                // Otherwise, build a translated route

                var routeUrl = CreateRouteUrl(translatedRouteUrl ?? routeSpec.RouteUrl,
                                              translatedRoutePrefix ?? routeSpec.RoutePrefixUrl,
                                              translatedAreaUrl ?? routeSpec.AreaUrl,
                                              routeSpec.IsAbsoluteUrl,
                                              routeSpec.UseLowercaseRoute);

                var translatedRoute = _routeFactory.CreateAttributeRoute(routeUrl,
                                                                         CreateRouteDefaults(routeSpec),
                                                                         CreateRouteConstraints(routeSpec),
                                                                         CreateRouteDataTokens(routeSpec));

                var routeName = CreateRouteName(routeSpec);
                if (routeName != null)
                {
                    translatedRoute.RouteName = routeName;
                    translatedRoute.DataTokens.Add("routeName", routeName);
                }

                translatedRoute.CultureName = cultureName;
                translatedRoute.DataTokens.Add("cultureName", cultureName);

                yield return(translatedRoute);
            }
        }
 private string CreateRouteUrl(IDictionary <string, object> defaults, RouteSpecification routeSpec)
 {
     return(CreateRouteUrl(routeSpec.RouteUrl,
                           routeSpec.RoutePrefixUrl,
                           routeSpec.AreaUrl,
                           defaults,
                           routeSpec));
 }
Exemplo n.º 7
0
 private string CreateRouteUrl(RouteSpecification routeSpec)
 {
     return(CreateRouteUrl(routeSpec.RouteUrl,
                           routeSpec.RoutePrefixUrl,
                           routeSpec.AreaUrl,
                           routeSpec.IsAbsoluteUrl,
                           routeSpec.UseLowercaseRoute));
 }
Exemplo n.º 8
0
        private RouteValueDictionary CreateRouteConstraints(RouteSpecification routeSpec)
        {
            var constraints = new RouteValueDictionary();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
            {
                constraints.Add("httpMethod", new RestfulHttpMethodConstraint(routeSpec.HttpMethods));
            }

            // Inline constraints
            foreach (var parameter in GetUrlParameterContents(routeSpec.Url).Where(p => Regex.IsMatch(p, @"^.*\(.*\)$")))
            {
                var indexOfOpenParen = parameter.IndexOf('(');
                var parameterName    = parameter.Substring(0, indexOfOpenParen);

                if (constraints.ContainsKey(parameterName))
                {
                    continue;
                }

                var regexPattern = parameter.Substring(indexOfOpenParen + 1, parameter.Length - indexOfOpenParen - 2);
                constraints.Add(parameterName, new RegexRouteConstraint(regexPattern));
            }

            // Attribute-based constraints
            foreach (var constraintAttribute in routeSpec.ConstraintAttributes)
            {
                if (constraints.ContainsKey(constraintAttribute.Key))
                {
                    continue;
                }

                constraints.Add(constraintAttribute.Key, constraintAttribute.Constraint);
            }

            var detokenizedUrl    = DetokenizeUrl(CreateRouteUrl(routeSpec));
            var urlParameterNames = GetUrlParameterNames(detokenizedUrl);

            // Convention-based constraints
            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;

                foreach (var urlParameterName in urlParameterNames.Where(n => Regex.IsMatch(n, pattern)))
                {
                    if (constraints.ContainsKey(urlParameterName))
                    {
                        continue;
                    }

                    constraints.Add(urlParameterName, defaultConstraint.Value);
                }
            }

            return(constraints);
        }
Exemplo n.º 9
0
 public AttributeRoute Build(RouteSpecification routeSpec)
 {
     return(new AttributeRoute(CreateRouteName(routeSpec),
                               CreateRouteUrl(routeSpec),
                               CreateRouteDefaults(routeSpec),
                               CreateRouteConstraints(routeSpec),
                               CreateRouteDataTokens(routeSpec),
                               _configuration.UseLowercaseRoutes));
 }
Exemplo n.º 10
0
 public AttributeRoute Build(RouteSpecification routeSpec)
 {
     return new AttributeRoute(CreateRouteName(routeSpec),
                               CreateRouteUrl(routeSpec),
                               CreateRouteDefaults(routeSpec),
                               CreateRouteConstraints(routeSpec),
                               CreateRouteDataTokens(routeSpec),
                               _configuration.UseLowercaseRoutes);
 }
Exemplo n.º 11
0
        private string CreateRouteName(RouteSpecification routeSpec)
        {
            if (routeSpec.RouteName.HasValue())
            {
                return(routeSpec.RouteName);
            }

            return(_configuration.AutoGenerateRouteNames ? _configuration.RouteNameBuilder(routeSpec) : null);
        }
        private IEnumerable <IAttributeRoute> BuildRoutes(RouteSpecification routeSpec)
        {
            // Get info needed to construct IAttributeRoute via factory method.
            IDictionary <string, object> defaults;
            IDictionary <string, object> queryStringDefaults;

            CreateRouteDefaults(routeSpec, out defaults, out queryStringDefaults);
            IDictionary <string, object> constraints;
            IDictionary <string, object> queryStringConstraints;

            CreateRouteConstraints(routeSpec, out constraints, out queryStringConstraints);
            var dataTokens = CreateRouteDataTokens(routeSpec);
            var url        = CreateRouteUrl(defaults, routeSpec);

            // Build the route.
            var routes = _routeFactory.CreateAttributeRoutes(url, defaults, constraints, dataTokens);

            // Extend the factory generated route:
            foreach (var route in routes)
            {
                var routeName = CreateRouteName(routeSpec);
                if (routeName.HasValue())
                {
                    route.RouteName = routeName;
                    route.DataTokens.Add("routeName", routeName);
                }

                route.QueryStringConstraints = queryStringConstraints;
                route.QueryStringDefaults    = queryStringDefaults;
                route.Translations           = CreateRouteTranslations(routeSpec);
                route.Subdomain                    = routeSpec.Subdomain;
                route.UseLowercaseRoute            = routeSpec.UseLowercaseRoute;
                route.PreserveCaseForUrlParameters = routeSpec.PreserveCaseForUrlParameters;
                route.AppendTrailingSlash          = routeSpec.AppendTrailingSlash;

                // Yield the default route first
                yield return(route);

                // Then yield the translations
                if (route.Translations != null)
                {
                    foreach (var translation in route.Translations)
                    {
                        // Backreference the default route.
                        translation.SourceLanguageRoute = route;

                        yield return(translation);
                    }
                }
            }
        }
Exemplo n.º 13
0
        private RouteValueDictionary CreateRouteDefaults(RouteSpecification routeSpec)
        {
            var defaults = new RouteValueDictionary
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };

            var urlParameters = GetUrlParameterContents(routeSpec.RouteUrl);

            // Inspect the url for optional parameters, specified with a leading or trailing (or both) ?
            foreach (var parameter in urlParameters.Where(p => Regex.IsMatch(p, @"^\?|\?$")))
            {
                var parameterName = parameter.Trim('?');

                if (defaults.ContainsKey(parameterName))
                {
                    continue;
                }

                defaults.Add(parameterName, UrlParameter.Optional);
            }

            // Inline defaults
            foreach (var parameter in urlParameters.Where(p => Regex.IsMatch(p, @"^.*=.*$")))
            {
                var indexOfEquals = parameter.IndexOf('=');
                var parameterName = parameter.Substring(0, indexOfEquals);

                if (defaults.ContainsKey(parameterName))
                {
                    continue;
                }

                var defaultValue = parameter.Substring(indexOfEquals + 1, parameter.Length - indexOfEquals - 1);
                defaults.Add(parameterName, defaultValue);
            }

            // Attribute-based defaults
            foreach (var defaultAttribute in routeSpec.DefaultAttributes)
            {
                if (defaults.ContainsKey(defaultAttribute.Key))
                {
                    continue;
                }

                defaults.Add(defaultAttribute.Key, defaultAttribute.Value);
            }

            return(defaults);
        }
        public string Execute(RouteSpecification routeSpec)
        {
            var areaPart  = routeSpec.AreaName.HasValue() ? "{0}_".FormatWith(routeSpec.AreaName) : null;
            var routeName = "{0}{1}_{2}".FormatWith(areaPart, routeSpec.ControllerName, routeSpec.ActionName);

            // Only register route names once, so first in wins.
            if (!_registeredRouteNames.Contains(routeName))
            {
                _registeredRouteNames.Add(routeName);
                return(routeName);
            }

            return(null);
        }
        public string Execute(RouteSpecification routeSpec)
        {
            var areaPart = routeSpec.AreaName.HasValue() ? "{0}_".FormatWith(routeSpec.AreaName) : null;
            var routeName = "{0}{1}_{2}".FormatWith(areaPart, routeSpec.ControllerName, routeSpec.ActionName);

            // Only register route names once, so first in wins.
            if (!_registeredRouteNames.Contains(routeName))
            {
                _registeredRouteNames.Add(routeName);
                return routeName;
            }

            return null;
        }
Exemplo n.º 16
0
        private IDictionary <string, object> CreateRouteDefaults(RouteSpecification routeSpec)
        {
            var defaults = new Dictionary <string, object>
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };

            var urlParameters = GetUrlParameterContents(routeSpec.RouteUrl).ToList();

            // Inspect the url for optional parameters, specified with a trailing ?
            foreach (var parameter in urlParameters.Where(p => p.EndsWith("?")))
            {
                var parameterName = parameter.TrimEnd('?');

                if (parameterName.Contains(':'))
                {
                    parameterName = parameterName.Substring(0, parameterName.IndexOf(':'));
                }

                if (defaults.ContainsKey(parameterName))
                {
                    continue;
                }

                defaults.Add(parameterName, _parameterFactory.Optional());
            }

            // Inline defaults
            foreach (var parameter in urlParameters.Where(p => p.Contains('=')))
            {
                var indexOfEquals = parameter.IndexOf('=');
                var parameterName = parameter.Substring(0, indexOfEquals);

                if (parameterName.Contains(':'))
                {
                    parameterName = parameterName.Substring(0, parameterName.IndexOf(':'));
                }

                if (defaults.ContainsKey(parameterName))
                {
                    continue;
                }

                var defaultValue = parameter.Substring(indexOfEquals + 1, parameter.Length - indexOfEquals - 1);
                defaults.Add(parameterName, defaultValue);
            }

            return(defaults);
        }
Exemplo n.º 17
0
        private string CreateRouteUrl(RouteSpecification routeSpec)
        {
            var detokenizedUrl    = DetokenizeUrl(routeSpec.Url);
            var urlParameterNames = GetUrlParameterNames(detokenizedUrl);

            // {controller} and {action} tokens are not valid
            if (urlParameterNames.Any(n => n.ValueEquals("controller")))
            {
                throw new AttributeRoutingException("{controller} is not a valid url parameter.");
            }
            if (urlParameterNames.Any(n => n.ValueEquals("action")))
            {
                throw new AttributeRoutingException("{action} is not a valid url parameter.");
            }

            // Explicitly defined area routes are not valid
            if (urlParameterNames.Any(n => n.ValueEquals("area")))
            {
                throw new AttributeRoutingException(
                          "{area} url parameters are not allowed. Specify the area name by using the RouteAreaAttribute.");
            }

            var urlBuilder = new StringBuilder(detokenizedUrl);

            // If this is not an absolute url, prefix with a route prefix or area name
            if (!routeSpec.IsAbsoluteUrl)
            {
                var delimitedRouteUrl = routeSpec.Url + "/";

                if (routeSpec.RoutePrefix.HasValue())
                {
                    var delimitedRoutePrefix = routeSpec.RoutePrefix + "/";
                    if (!delimitedRouteUrl.StartsWith(delimitedRoutePrefix))
                    {
                        urlBuilder.Insert(0, delimitedRoutePrefix);
                    }
                }

                if (routeSpec.AreaUrl.HasValue())
                {
                    var delimitedAreaUrl = routeSpec.AreaUrl + "/";
                    if (!delimitedRouteUrl.StartsWith(delimitedAreaUrl))
                    {
                        urlBuilder.Insert(0, delimitedAreaUrl);
                    }
                }
            }

            return(urlBuilder.ToString().Trim('/'));
        }
Exemplo n.º 18
0
        private IEnumerable <AttributeRoute> CreateRouteTranslations(RouteSpecification routeSpec)
        {
            // If no translation provider, then get out of here.
            if (!_configuration.TranslationProviders.Any())
            {
                yield break;
            }

            // Merge all the culture names from the various providers.
            var cultureNames = _configuration.GetTranslationProviderCultureNames();

            // Built the route translations,
            // choosing the first available translated route component from among the providers
            foreach (var cultureName in cultureNames)
            {
                string translatedRouteUrl      = null,
                         translatedRoutePrefix = null,
                         translatedAreaUrl     = null;

                foreach (var provider in _configuration.TranslationProviders)
                {
                    translatedRouteUrl    = translatedRouteUrl ?? provider.TranslateRouteUrl(cultureName, routeSpec);
                    translatedRoutePrefix = translatedRoutePrefix ?? provider.TranslateRoutePrefix(cultureName, routeSpec);
                    translatedAreaUrl     = translatedAreaUrl ?? provider.TranslateAreaUrl(cultureName, routeSpec);
                }

                if (translatedRouteUrl == null && translatedRoutePrefix == null && translatedAreaUrl == null)
                {
                    continue;
                }

                var translatedRoute =
                    new AttributeRoute(CreateRouteUrl(translatedRouteUrl ?? routeSpec.RouteUrl,
                                                      translatedRoutePrefix ?? routeSpec.RoutePrefixUrl,
                                                      translatedAreaUrl ?? routeSpec.AreaUrl,
                                                      routeSpec.IsAbsoluteUrl),
                                       CreateRouteDefaults(routeSpec),
                                       CreateRouteConstraints(routeSpec),
                                       CreateRouteDataTokens(routeSpec),
                                       _configuration)
                {
                    CultureName = cultureName,
                };

                translatedRoute.DataTokens.Add("cultureName", cultureName);

                yield return(translatedRoute);
            }
        }
Exemplo n.º 19
0
        private string CreateRouteName(RouteSpecification routeSpec)
        {
            if (routeSpec.RouteName.HasValue())
            {
                return(routeSpec.RouteName);
            }

            if (_configuration.AutoGenerateRouteNames)
            {
                var area = (routeSpec.AreaName.HasValue()) ? routeSpec.AreaName + "_" : null;
                return("{0}{1}_{2}".FormatWith(area, routeSpec.ControllerName, routeSpec.ActionName));
            }

            return(null);
        }
Exemplo n.º 20
0
        private IDictionary <string, object> CreateRouteDataTokens(RouteSpecification routeSpec)
        {
            var dataTokens = new Dictionary <string, object>
            {
                { "namespaces", new[] { routeSpec.ControllerType.Namespace } }
            };

            if (routeSpec.AreaName.HasValue())
            {
                dataTokens.Add("area", routeSpec.AreaName);
                dataTokens.Add("UseNamespaceFallback", false);
            }

            return(dataTokens);
        }
        private IDictionary <string, object> CreateRouteDataTokens(RouteSpecification routeSpec)
        {
            var dataTokens = new Dictionary <string, object>
            {
                { "namespaces", new[] { routeSpec.ControllerType.Namespace } },
                { "actionMethod", routeSpec.ActionMethod },
                { "defaultSubdomain", _configuration.DefaultSubdomain }
            };

            if (routeSpec.HttpMethods.Any())
            {
                dataTokens.Add("httpMethods", routeSpec.HttpMethods);
            }

            if (routeSpec.AreaName.HasValue())
            {
                dataTokens.Add("area", routeSpec.AreaName);
                dataTokens.Add("UseNamespaceFallback", false);
            }

            return(dataTokens);
        }
        public string Execute(RouteSpecification routeSpec)
        {
            var routeNameBuilder = new StringBuilder();

            if (routeSpec.AreaName.HasValue())
            {
                routeNameBuilder.AppendFormat("{0}_", routeSpec.AreaName);
            }

            routeNameBuilder.Append(routeSpec.ControllerName);
            routeNameBuilder.AppendFormat("_{0}", routeSpec.ActionName);

            // Ensure route names are unique.
            var routeName             = routeNameBuilder.ToString();
            var routeNameIsRegistered = _registeredRouteNames.Contains(routeName);

            if (routeNameIsRegistered)
            {
                // Prefix with the first verb (assuming this is the primary verb) if not a GET route.
                if (routeSpec.HttpMethods.Length > 0 && !routeSpec.HttpMethods.Contains("GET"))
                {
                    routeNameBuilder.AppendFormat("_{0}", routeSpec.HttpMethods.FirstOrDefault());
                }

                // Suffixing with an index if necessary to disambiguate.
                routeName = routeNameBuilder.ToString();
                var count = _registeredRouteNames.Count(n => n == routeName || n.StartsWith(routeName + "_"));
                if (count > 0)
                {
                    routeNameBuilder.AppendFormat("_{0}", count);
                }
            }

            routeName = routeNameBuilder.ToString();

            _registeredRouteNames.Add(routeName);

            return(routeName);
        }
Exemplo n.º 23
0
        private IEnumerable <IAttributeRoute> Build(RouteSpecification routeSpec)
        {
            var route = _routeFactory.CreateAttributeRoute(CreateRouteUrl(routeSpec),
                                                           CreateRouteDefaults(routeSpec),
                                                           CreateRouteConstraints(routeSpec),
                                                           CreateRouteDataTokens(routeSpec));

            var routeName = CreateRouteName(routeSpec);

            if (routeName.HasValue())
            {
                route.RouteName = routeName;
                route.DataTokens.Add("routeName", routeName);
            }

            route.Translations                 = CreateRouteTranslations(routeSpec);
            route.Subdomain                    = routeSpec.Subdomain;
            route.UseLowercaseRoute            = routeSpec.UseLowercaseRoute;
            route.PreserveCaseForUrlParameters = routeSpec.PreserveCaseForUrlParameters;
            route.AppendTrailingSlash          = routeSpec.AppendTrailingSlash;

            // Yield the default route first
            yield return(route);

            // Then yield the translations
            if (route.Translations == null)
            {
                yield break;
            }

            foreach (var translation in route.Translations)
            {
                // Backreference the default route.
                translation.DefaultRouteContainer = route;

                yield return(translation);
            }
        }
        public string Execute(RouteSpecification routeSpec)
        {
            var routeNameBuilder = new StringBuilder();

            if (routeSpec.AreaName.HasValue())
                routeNameBuilder.AppendFormat("{0}_", routeSpec.AreaName);

            routeNameBuilder.Append(routeSpec.ControllerName);
            routeNameBuilder.AppendFormat("_{0}", routeSpec.ActionName);

            // Ensure route names are unique.
            var routeName = routeNameBuilder.ToString();
            var routeNameIsRegistered = _registeredRouteNames.Contains(routeName);
            if (routeNameIsRegistered)
            {
                // Prefix with the first verb (assuming this is the primary verb) if not a GET route.
                if (routeSpec.HttpMethods.Length > 0 && !routeSpec.HttpMethods.Contains("GET"))
                {
                    routeNameBuilder.AppendFormat("_{0}", routeSpec.HttpMethods.FirstOrDefault());
                }

                // Suffixing with an index if necessary to disambiguate.
                routeName = routeNameBuilder.ToString();
                var count = _registeredRouteNames.Count(n => n == routeName || n.StartsWith(routeName + "_"));
                if (count > 0)
                {
                    routeNameBuilder.AppendFormat("_{0}", count);
                }
            }

            routeName = routeNameBuilder.ToString();

            _registeredRouteNames.Add(routeName);

            return routeName;
        }
        private void CreateRouteConstraints(RouteSpecification routeSpec, out IDictionary <string, object> constraints, out IDictionary <string, object> queryStringConstraints)
        {
            // Going to return individual collections for:
            // - path routes constraints (which will go into the generated route's Constraints prop),
            // - and query string route constraints (which will not work perfectly with the MS bits, and need special treatment by IAttributeRoute impls).
            constraints            = new Dictionary <string, object>();
            queryStringConstraints = new Dictionary <string, object>();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
            {
                constraints.Add("inboundHttpMethod", _routeConstraintFactory.CreateInboundHttpMethodConstraint(routeSpec.HttpMethods));
            }

            // Work from a complete, tokenized url; ie: support constraints in area urls, route prefix urls, and route urls.
            var tokenizedUrl  = BuildTokenizedUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec);
            var urlParameters = GetUrlParameterContents(tokenizedUrl).ToList();

            // Need to keep track of which are path and query params.
            var pathOnlyUrl           = RemoveQueryString(tokenizedUrl);
            var pathOnlyUrlParameters = GetUrlParameterContents(pathOnlyUrl);
            var queryStringParameters = urlParameters.Except(pathOnlyUrlParameters).ToList();

            // Inline constraints
            foreach (var parameter in urlParameters)
            {
                // Keep track of whether this param is optional or in the querystring,
                // because we wrap the final constraint if so.
                var parameterIsOptional      = parameter.EndsWith("?");
                var parameterIsInQueryString = queryStringParameters.Contains(parameter);

                // If this is a path parameter and doesn't have a constraint, then skip it.
                if (!parameterIsInQueryString && !parameter.Contains(":"))
                {
                    continue;
                }

                // Strip off everything related to defaults and break into sections.
                var cleanParameter = parameter.TrimEnd('?').Split('=').FirstOrDefault();
                var sections       = cleanParameter.SplitAndTrim(":");

                // Do not override default constraints
                var parameterName = sections.First();
                if (constraints.ContainsKey(parameterName))
                {
                    continue;
                }

                // Add constraints for each inline definition
                var inlineConstraints     = new List <object>();
                var constraintDefinitions = sections.Skip(1);
                foreach (var definition in constraintDefinitions)
                {
                    string constraintName;
                    object constraint;

                    if (ConstraintParamsRegex.IsMatch(definition))
                    {
                        // Constraint of the form "firstName:string(50)"
                        var indexOfOpenParen = definition.IndexOf('(');
                        constraintName = definition.Substring(0, indexOfOpenParen);

                        // Parse constraint params.
                        // NOTE: Splitting on commas only applies to non-regex constraints.
                        var constraintParamsRaw = definition.Substring(indexOfOpenParen + 1, definition.Length - indexOfOpenParen - 2);
                        var constraintParams    = constraintName.ValueEquals("regex")
                                                   ? new[] { constraintParamsRaw }
                                                   : constraintParamsRaw.SplitAndTrim(",");

                        constraint = _routeConstraintFactory.CreateInlineRouteConstraint(constraintName, constraintParams);
                    }
                    else
                    {
                        // Constraint of the form "id:int"
                        constraintName = definition;
                        constraint     = _routeConstraintFactory.CreateInlineRouteConstraint(constraintName);
                    }

                    if (constraint == null)
                    {
                        throw new AttributeRoutingException(
                                  "Could not find an available inline constraint for \"{0}\".".FormatWith(constraintName));
                    }

                    inlineConstraints.Add(constraint);
                }

                // Wrap constraints in the following priority:
                object finalConstraint;

                // 1. If more than one constraint, wrap in a compound constraint.
                if (inlineConstraints.Count > 1)
                {
                    finalConstraint = _routeConstraintFactory.CreateCompoundRouteConstraint(inlineConstraints.ToArray());
                }
                else
                {
                    finalConstraint = inlineConstraints.FirstOrDefault();
                }

                // 2. If the constraint is in the querystring, wrap in a query string constraint.
                if (parameterIsInQueryString)
                {
                    finalConstraint = _routeConstraintFactory.CreateQueryStringRouteConstraint(finalConstraint);
                }

                // 3. If the constraint is optional, wrap in an optional constraint.
                if (parameterIsOptional)
                {
                    finalConstraint = _routeConstraintFactory.CreateOptionalRouteConstraint(finalConstraint);
                }

                // Add the constraints to the appropriate collection.
                if (parameterIsInQueryString)
                {
                    queryStringConstraints.Add(parameterName, finalConstraint);
                }
                else
                {
                    constraints.Add(parameterName, finalConstraint);
                }
            } // ... go to next parameter

            // Globally configured constraints - have to treat path params differently than query params.
            var    detokenizedUrl = DetokenizeUrl(tokenizedUrl);
            string path, query;

            detokenizedUrl.GetPathAndQuery(out path, out query);
            var urlPathParameterNames  = GetUrlParameterContents(path).ToArray();
            var urlQueryParameterNames = GetUrlParameterContents(query).ToArray();

            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                ApplyDefaultRouteConstraint(urlPathParameterNames, defaultConstraint, constraints, false);
                ApplyDefaultRouteConstraint(urlQueryParameterNames, defaultConstraint, queryStringConstraints, true);
            }
        }
Exemplo n.º 26
0
        /// <summary>
        /// Looks at _configuration.ApiVersions to see what versions are supported, and generates a list 
        /// of versions for each between min and max.
        /// If no versions are defined in configuration, always returns one null version.
        /// </summary>
        /// <param name="minVersion"></param>
        /// <param name="maxVersion"></param>
        /// <returns></returns>
        private IEnumerable<SemanticVersion> GenerateRouteVersions(RouteSpecification routeSpec)
        {
            if (!routeSpec.IsVersioned || (_configuration.ApiVersions == null) && (_configuration.ApiVersions.Count == 0))
            {
                return new List<SemanticVersion>() { null };
            }

            return (from version in _configuration.ApiVersions
                    where (routeSpec.MinVersion == null || version >= routeSpec.MinVersion)
                        && (routeSpec.MaxVersion == null || version <= routeSpec.MaxVersion)
                    select version);
        }
        private IDictionary<string, object> CreateRouteDefaults(RouteSpecification routeSpec)
        {
            var defaults = new Dictionary<string, object>
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };

            var urlParameters = GetUrlParameterContents(routeSpec.RouteUrl).ToList();

            // Inspect the url for optional parameters, specified with a trailing ?
            foreach (var parameter in urlParameters.Where(p => p.EndsWith("?")))
            {
                var parameterName = parameter.TrimEnd('?');

                if (parameterName.Contains(':'))
                    parameterName = parameterName.Substring(0, parameterName.IndexOf(':'));

                if (defaults.ContainsKey(parameterName))
                    continue;

                defaults.Add(parameterName, _parameterFactory.Optional());
            }

            // Inline defaults
            foreach (var parameter in urlParameters.Where(p => p.Contains('=')))
            {
                var indexOfEquals = parameter.IndexOf('=');
                var parameterName = parameter.Substring(0, indexOfEquals);

                if (parameterName.Contains(':'))
                    parameterName = parameterName.Substring(0, parameterName.IndexOf(':'));

                if (defaults.ContainsKey(parameterName))
                    continue;

                var defaultValue = parameter.Substring(indexOfEquals + 1, parameter.Length - indexOfEquals - 1);
                defaults.Add(parameterName, defaultValue);
            }

            return defaults;
        }
Exemplo n.º 28
0
        private IDictionary <string, object> CreateRouteConstraints(RouteSpecification routeSpec)
        {
            var constraints = new Dictionary <string, object>();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
            {
                constraints.Add("httpMethod", _routeConstraintFactory.CreateRestfulHttpMethodConstraint(routeSpec.HttpMethods));
            }

            // Work from a complete, tokenized url; ie: support constraints in area urls, route prefix urls, and route urls.
            var tokenizedUrl  = BuildTokenizedUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec.IsAbsoluteUrl);
            var urlParameters = GetUrlParameterContents(tokenizedUrl).ToList();

            // Inline constraints
            var constraintFactory = _configuration.RouteConstraintFactory;

            foreach (var parameter in urlParameters.Where(p => p.Contains(":")))
            {
                // Keep track of whether this param is optional,
                // because we wrap the final constraint if so.
                var parameterIsOptional = parameter.EndsWith("?");

                // Strip off everything related to defaults.
                var cleanParameter = parameter.TrimEnd('?').Split('=').FirstOrDefault();

                var sections      = cleanParameter.SplitAndTrim(":");
                var parameterName = sections.First();

                // Do not override default or legacy inline constraints
                if (constraints.ContainsKey(parameterName))
                {
                    continue;
                }

                // Add constraints for each inline definition
                var inlineConstraints     = new List <object>();
                var constraintDefinitions = sections.Skip(1);
                foreach (var definition in constraintDefinitions)
                {
                    string constraintName;
                    object constraint;

                    if (Regex.IsMatch(definition, @"^.*\(.*\)$"))
                    {
                        // Constraint of the form "firstName:string(50)"
                        var indexOfOpenParen = definition.IndexOf('(');
                        constraintName = definition.Substring(0, indexOfOpenParen);
                        var constraintParams = definition.Substring(indexOfOpenParen + 1, definition.Length - indexOfOpenParen - 2).SplitAndTrim(",");
                        constraint = constraintFactory.CreateInlineRouteConstraint(constraintName, constraintParams);
                    }
                    else
                    {
                        // Constraint of the form "id:int"
                        constraintName = definition;
                        constraint     = constraintFactory.CreateInlineRouteConstraint(constraintName);
                    }

                    if (constraint == null)
                    {
                        throw new AttributeRoutingException(
                                  "Could not find an available inline constraint for \"{0}\".".FormatWith(constraintName));
                    }

                    inlineConstraints.Add(constraint);
                }

                // Apply the constraint to the parameter.
                // Wrap multiple constraints in a compound constraint wrapper.
                // Wrap constraints for optional params in an optional constraint wrapper.
                var finalConstraint = (inlineConstraints.Count == 1)
                                          ? inlineConstraints.Single()
                                          : constraintFactory.CreateCompoundRouteConstraint(inlineConstraints.ToArray());

                if (parameterIsOptional)
                {
                    constraints.Add(parameterName, constraintFactory.CreateOptionalRouteConstraint(finalConstraint));
                }
                else
                {
                    constraints.Add(parameterName, finalConstraint);
                }
            }

            // Globally configured constraints
            var detokenizedPrefixedUrl = DetokenizeUrl(tokenizedUrl);
            var urlParameterNames      = GetUrlParameterContents(detokenizedPrefixedUrl).ToList();

            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;

                foreach (var urlParameterName in urlParameterNames.Where(n => Regex.IsMatch(n, pattern)))
                {
                    if (constraints.ContainsKey(urlParameterName))
                    {
                        continue;
                    }

                    constraints.Add(urlParameterName, defaultConstraint.Value);
                }
            }

            return(constraints);
        }
Exemplo n.º 29
0
        private string CreateRouteUrl(RouteSpecification routeSpec)
        {
            var detokenizedUrl = DetokenizeUrl(routeSpec.Url);
            var urlParameterNames = GetUrlParameterNames(detokenizedUrl);

            // {controller} and {action} tokens are not valid
            if (urlParameterNames.Any(n => n.ValueEquals("controller")))
                throw new AttributeRoutingException("{controller} is not a valid url parameter.");
            if (urlParameterNames.Any(n => n.ValueEquals("action")))
                throw new AttributeRoutingException("{action} is not a valid url parameter.");

            // Explicitly defined area routes are not valid
            if (urlParameterNames.Any(n => n.ValueEquals("area")))
                throw new AttributeRoutingException(
                    "{area} url parameters are not allowed. Specify the area name by using the RouteAreaAttribute.");

            var urlBuilder = new StringBuilder(detokenizedUrl);

            // If this is not an absolute url, prefix with a route prefix or area name
            if (!routeSpec.IsAbsoluteUrl)
            {
                if (routeSpec.RoutePrefix.HasValue() && !routeSpec.Url.StartsWith(routeSpec.RoutePrefix))
                    urlBuilder.Insert(0, routeSpec.RoutePrefix + "/");

                if (routeSpec.AreaUrl.HasValue() && !routeSpec.Url.StartsWith(routeSpec.AreaUrl))
                    urlBuilder.Insert(0, routeSpec.AreaUrl + "/");
            }

            return urlBuilder.ToString().Trim('/');
        }
        private void CreateRouteDefaults(RouteSpecification routeSpec, out IDictionary <string, object> defaults, out IDictionary <string, object> queryStringDefaults)
        {
            // Going to return individual collections for:
            // - path routes defaults (which will go into the generated route's Defaults prop),
            // - and query string route defaults (which will not work perfectly with the MS bits, and need special treatment by IAttributeRoute impls).
            defaults = new Dictionary <string, object>
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };
            queryStringDefaults = new Dictionary <string, object>();

            // Work from a complete, tokenized url; ie: support constraints in area urls, route prefix urls, and route urls.
            var tokenizedUrl  = BuildTokenizedUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec);
            var urlParameters = GetUrlParameterContents(tokenizedUrl).ToList();

            // Need to keep track of which are path and query params.
            var pathOnlyUrl           = RemoveQueryString(tokenizedUrl);
            var pathOnlyUrlParameters = GetUrlParameterContents(pathOnlyUrl).ToList();
            var queryStringParameters = urlParameters.Except(pathOnlyUrlParameters).ToList();

            // Inspect the url path for optional parameters and default values.
            foreach (var parameter in urlParameters)
            {
                // Does this param have a default value or is it optional?
                var isOptional    = parameter.EndsWith("?");
                var indexOfEquals = parameter.IndexOf('=');
                if (!isOptional && indexOfEquals == -1)
                {
                    continue;
                }

                // Keep track if this is a querystring param
                var parameterIsInQueryString = queryStringParameters.Contains(parameter);

                // Strip off inline constraints, defaults, and optional tokens.
                var parameterName = DetokenizeUrlParamContentsRegex.Replace(parameter, "");

                // Do not override default defaults.
                if (defaults.ContainsKey(parameterName))
                {
                    continue;
                }

                object defaultValue;
                if (isOptional)
                {
                    defaultValue = _parameterFactory.Optional();
                }
                else // It has a default value.
                {
                    defaultValue = parameter.Substring(indexOfEquals + 1, parameter.Length - indexOfEquals - 1);
                }

                if (parameterIsInQueryString)
                {
                    queryStringDefaults.Add(parameterName, defaultValue);
                }
                else
                {
                    defaults.Add(parameterName, defaultValue);
                }
            }
        }
Exemplo n.º 31
0
        private string CreateRouteUrl(string routeUrl, string routePrefix, string areaUrl, IDictionary<string, object> defaults, RouteSpecification routeSpec)
        {
            var tokenizedUrl = BuildTokenizedUrl(routeUrl, routePrefix, areaUrl, routeSpec);
            var tokenizedPath = RemoveQueryString(tokenizedUrl);
            var detokenizedPath = DetokenizeUrl(tokenizedPath);
            var urlParameterNames = GetUrlParameterContents(detokenizedPath).ToList();

            var urlBuilder = new StringBuilder(detokenizedPath);

            // Replace {controller} URL param with default value.
            if (urlParameterNames.Any(n => n.ValueEquals("controller")))
            {
                urlBuilder.Replace("{controller}", (string)defaults["controller"]);
            }

            // Replace {action} URL param with default value.
            if (urlParameterNames.Any(n => n.ValueEquals("action")))
            {
                urlBuilder.Replace("{action}", (string)defaults["action"]);
            }

            // Explicitly defined area routes are not valid
            if (urlParameterNames.Any(n => n.ValueEquals("area")))
            {
                throw new AttributeRoutingException(
                    "{area} url parameters are not allowed. Specify the area name by using the RouteAreaAttribute.");
            }

            // If we are lowercasing routes, then lowercase everything but the route params
            var lower = routeSpec.UseLowercaseRoute.GetValueOrDefault(_configuration.UseLowercaseRoutes);
            if (lower)
            {
                for (var i = 0; i < urlBuilder.Length; i++)
                {
                    var c = urlBuilder[i];
                    if (Char.IsUpper(c))
                    {
                        urlBuilder[i] = Char.ToLower(c);
                    }
                    else if (c == '{')
                    {
                        while (urlBuilder[i] != '}' && i < urlBuilder.Length)
                        {
                            i++;
                        }
                    }
                }
            }

            return urlBuilder.ToString().Trim('/');
        }
Exemplo n.º 32
0
        private RouteValueDictionary CreateRouteDefaults(RouteSpecification routeSpec)
        {
            var defaults = new RouteValueDictionary
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };

            foreach (var defaultAttribute in routeSpec.DefaultAttributes.Where(d => !defaults.ContainsKey(d.Key)))
                defaults.Add(defaultAttribute.Key, defaultAttribute.Value);

            // Inspect the url for optional parameters, specified with a leading ?
            var optionalParameterDefaults =
                from parameter in GetUrlParameterContents(routeSpec.Url)
                where parameter.StartsWith("?")
                let parameterName = parameter.TrimStart('?')
                select new RouteDefaultAttribute(parameterName, UrlParameter.Optional);

            foreach (var defautAttribute in optionalParameterDefaults.Where(d => !defaults.ContainsKey(d.Key)))
                defaults.Add(defautAttribute.Key, defautAttribute.Value);

            return defaults;
        }
Exemplo n.º 33
0
        private IEnumerable<IAttributeRoute> CreateRouteTranslations(RouteSpecification routeSpec)
        {
            // If no translation provider, then get out of here.
            if (!_configuration.TranslationProviders.Any())
                yield break;

            // Merge all the culture names from the various providers.
            var cultureNames = _configuration.GetTranslationProviderCultureNames();

            // Built the route translations,
            // choosing the first available translated route component from among the providers
            foreach (var cultureName in cultureNames)
            {
                string translatedRouteUrl = null,
                       translatedRoutePrefix = null,
                       translatedAreaUrl = null;

                foreach (var provider in _configuration.TranslationProviders)
                {
                    translatedRouteUrl = translatedRouteUrl ?? provider.TranslateRouteUrl(cultureName, routeSpec);
                    translatedRoutePrefix = translatedRoutePrefix ?? provider.TranslateRoutePrefix(cultureName, routeSpec);
                    translatedAreaUrl = translatedAreaUrl ?? provider.TranslateAreaUrl(cultureName, routeSpec);
                }

                // If nothing is translated, then bail.
                if (translatedRouteUrl == null && translatedRoutePrefix == null && translatedAreaUrl == null)
                {
                    continue;
                }

                //*********************************************
                // Otherwise, build a translated route

                // REVIEW: Could probably forgo processing defaults, constraints, and data tokens for translated routes.

                IDictionary<string, object> defaults;
                IDictionary<string, object> queryStringDefaults;
                CreateRouteDefaults(routeSpec, out defaults, out queryStringDefaults);
                IDictionary<string, object> constraints;
                IDictionary<string, object> queryStringConstraints;
                CreateRouteConstraints(routeSpec, out constraints, out queryStringConstraints);
                var dataTokens = CreateRouteDataTokens(routeSpec);
                var routeUrl = CreateRouteUrl(translatedRouteUrl ?? routeSpec.RouteUrl,
                                              translatedRoutePrefix ?? routeSpec.RoutePrefixUrl,
                                              translatedAreaUrl ?? routeSpec.AreaUrl,
                                              defaults,
                                              routeSpec);

                var translatedRoutes = _routeFactory.CreateAttributeRoutes(routeUrl, defaults, constraints, dataTokens);

                foreach (var translatedRoute in translatedRoutes)
                {
                    var routeName = CreateRouteName(routeSpec);
                    if (routeName != null)
                    {
                        translatedRoute.RouteName = routeName;
                        translatedRoute.DataTokens.Add("routeName", routeName);
                    }

                    translatedRoute.QueryStringConstraints = queryStringConstraints;
                    translatedRoute.QueryStringDefaults = queryStringDefaults;
                    translatedRoute.CultureName = cultureName;
                    translatedRoute.DataTokens.Add("cultureName", cultureName);

                    yield return translatedRoute;
                }
            }
        }
Exemplo n.º 34
0
 private string CreateRouteUrl(IDictionary<string, object> defaults, RouteSpecification routeSpec)
 {
     return CreateRouteUrl(routeSpec.RouteUrl,
                           routeSpec.RoutePrefixUrl,
                           routeSpec.AreaUrl,
                           defaults,
                           routeSpec);
 }
Exemplo n.º 35
0
        private string CreateRouteName(RouteSpecification routeSpec)
        {
            if (routeSpec.RouteName.HasValue())
            {
                return routeSpec.RouteName;
            }

            return _configuration.AutoGenerateRouteNames ? _configuration.RouteNameBuilder(routeSpec) : null;
        }
Exemplo n.º 36
0
        private RouteValueDictionary CreateRouteConstraints(RouteSpecification routeSpec, bool isTranslation = false)
        {
            var constraints = new RouteValueDictionary();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
                constraints.Add("httpMethod", new RestfulHttpMethodConstraint(routeSpec.HttpMethods));

            // Inline constraints
            foreach (var parameter in GetUrlParameterContents(routeSpec.RouteUrl).Where(p => Regex.IsMatch(p, @"^.*\(.*\)$")))
            {
                var indexOfOpenParen = parameter.IndexOf('(');
                var parameterName = parameter.Substring(0, indexOfOpenParen);

                if (constraints.ContainsKey(parameterName))
                    continue;

                var regexPattern = parameter.Substring(indexOfOpenParen + 1, parameter.Length - indexOfOpenParen - 2);
                constraints.Add(parameterName, new RegexRouteConstraint(regexPattern));
            }

            // Attribute-based constraints
            foreach (var constraintAttribute in routeSpec.ConstraintAttributes)
            {
                if (constraints.ContainsKey(constraintAttribute.Key))
                    continue;

                constraints.Add(constraintAttribute.Key, constraintAttribute.Constraint);
            }

            var detokenizedUrl = DetokenizeUrl(CreateRouteUrl(routeSpec));
            var urlParameterNames = GetUrlParameterContents(detokenizedUrl);

            // Convention-based constraints
            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;

                foreach (var urlParameterName in urlParameterNames.Where(n => Regex.IsMatch(n, pattern)))
                {
                    if (constraints.ContainsKey(urlParameterName))
                        continue;

                    constraints.Add(urlParameterName, defaultConstraint.Value);
                }
            }

            return constraints;
        }
Exemplo n.º 37
0
        private IDictionary<string, object> CreateRouteDataTokens(RouteSpecification routeSpec)
        {
            var dataTokens = new Dictionary<string, object>
            {
                { "namespaces", new[] { routeSpec.ControllerType.Namespace } },
                { "actionMethod", routeSpec.ActionMethod },
                { "defaultSubdomain", _configuration.DefaultSubdomain}
            };

            if (routeSpec.HttpMethods.Any())
            {
                dataTokens.Add("httpMethods", routeSpec.HttpMethods);
            }

            if (routeSpec.AreaName.HasValue())
            {
                dataTokens.Add("area", routeSpec.AreaName);
                dataTokens.Add("UseNamespaceFallback", false);
            }

            return dataTokens;
        }
Exemplo n.º 38
0
        private void CreateRouteConstraints(RouteSpecification routeSpec, out IDictionary<string, object> constraints, out IDictionary<string, object> queryStringConstraints)
        {
            // Going to return individual collections for:
            // - path routes constraints (which will go into the generated route's Constraints prop),
            // - and query string route constraints (which will not work perfectly with the MS bits, and need special treatment by IAttributeRoute impls).
            constraints = new Dictionary<string, object>();
            queryStringConstraints = new Dictionary<string, object>();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
            {
                constraints.Add("inboundHttpMethod", _routeConstraintFactory.CreateInboundHttpMethodConstraint(routeSpec.HttpMethods));
            }

            // Work from a complete, tokenized url; ie: support constraints in area urls, route prefix urls, and route urls.
            var tokenizedUrl = BuildTokenizedUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec);
            var urlParameters = GetUrlParameterContents(tokenizedUrl).ToList();

            // Need to keep track of which are path and query params.
            var pathOnlyUrl = RemoveQueryString(tokenizedUrl);
            var pathOnlyUrlParameters = GetUrlParameterContents(pathOnlyUrl);
            var queryStringParameters = urlParameters.Except(pathOnlyUrlParameters).ToList();

            // Inline constraints
            foreach (var parameter in urlParameters)
            {
                // Keep track of whether this param is optional or in the querystring,
                // because we wrap the final constraint if so.
                var parameterIsOptional = parameter.EndsWith("?");
                var parameterIsInQueryString = queryStringParameters.Contains(parameter);

                // If this is a path parameter and doesn't have a constraint, then skip it.
                if (!parameterIsInQueryString && !parameter.Contains(":"))
                {
                    continue;
                }

                // Strip off everything related to defaults and break into sections.
                var cleanParameter = parameter.TrimEnd('?').Split('=').FirstOrDefault();
                var sections = cleanParameter.SplitAndTrim(":");

                // Do not override default constraints
                var parameterName = sections.First();
                if (constraints.ContainsKey(parameterName))
                {
                    continue;
                }

                // Add constraints for each inline definition
                var inlineConstraints = new List<object>();
                var constraintDefinitions = sections.Skip(1);
                foreach (var definition in constraintDefinitions)
                {
                    string constraintName;
                    object constraint;

                    if (ConstraintParamsRegex.IsMatch(definition))
                    {
                        // Constraint of the form "firstName:string(50)"
                        var indexOfOpenParen = definition.IndexOf('(');
                        constraintName = definition.Substring(0, indexOfOpenParen);

                        // Parse constraint params.
                        // NOTE: Splitting on commas only applies to non-regex constraints.
                        var constraintParamsRaw = definition.Substring(indexOfOpenParen + 1, definition.Length - indexOfOpenParen - 2);
                        var constraintParams = constraintName.ValueEquals("regex")
                                                   ? new[] { constraintParamsRaw }
                                                   : constraintParamsRaw.SplitAndTrim(",");

                        constraint = _routeConstraintFactory.CreateInlineRouteConstraint(constraintName, constraintParams);
                    }
                    else
                    {
                        // Constraint of the form "id:int"
                        constraintName = definition;
                        constraint = _routeConstraintFactory.CreateInlineRouteConstraint(constraintName);
                    }

                    if (constraint == null)
                    {
                        throw new AttributeRoutingException(
                            "Could not find an available inline constraint for \"{0}\".".FormatWith(constraintName));
                    }

                    inlineConstraints.Add(constraint);
                }

                // Wrap constraints in the following priority:
                object finalConstraint;

                // 1. If more than one constraint, wrap in a compound constraint.
                if (inlineConstraints.Count > 1)
                {
                    finalConstraint = _routeConstraintFactory.CreateCompoundRouteConstraint(inlineConstraints.ToArray());
                }
                else
                {
                    finalConstraint = inlineConstraints.FirstOrDefault();
                }

                // 2. If the constraint is in the querystring, wrap in a query string constraint.
                if (parameterIsInQueryString)
                {
                    finalConstraint = _routeConstraintFactory.CreateQueryStringRouteConstraint(finalConstraint);
                }

                // 3. If the constraint is optional, wrap in an optional constraint.
                if (parameterIsOptional)
                {
                    finalConstraint = _routeConstraintFactory.CreateOptionalRouteConstraint(finalConstraint);
                }

                // Add the constraints to the appropriate collection.
                if (parameterIsInQueryString)
                {
                    queryStringConstraints.Add(parameterName, finalConstraint);
                }
                else
                {
                    constraints.Add(parameterName, finalConstraint);
                }
            } // ... go to next parameter

            // Globally configured constraints - have to treat path params differently than query params.
            var detokenizedUrl = DetokenizeUrl(tokenizedUrl);
            string path, query;
            detokenizedUrl.GetPathAndQuery(out path, out query);
            var urlPathParameterNames = GetUrlParameterContents(path).ToArray();
            var urlQueryParameterNames = GetUrlParameterContents(query).ToArray();

            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                ApplyDefaultRouteConstraint(urlPathParameterNames, defaultConstraint, constraints, false);
                ApplyDefaultRouteConstraint(urlQueryParameterNames, defaultConstraint, queryStringConstraints, true);
            }
        }
Exemplo n.º 39
0
        private IEnumerable<IAttributeRoute> BuildRoutes(RouteSpecification routeSpec)
        {
            // Get info needed to construct IAttributeRoute via factory method.
            IDictionary<string, object> defaults;
            IDictionary<string, object> queryStringDefaults;
            CreateRouteDefaults(routeSpec, out defaults, out queryStringDefaults);
            IDictionary<string, object> constraints;
            IDictionary<string, object> queryStringConstraints;
            CreateRouteConstraints(routeSpec, out constraints, out queryStringConstraints);
            var dataTokens = CreateRouteDataTokens(routeSpec);
            var url = CreateRouteUrl(defaults, routeSpec);

            // Build the route.
            var routes = _routeFactory.CreateAttributeRoutes(url, defaults, constraints, dataTokens);

            // Extend the factory generated route:
            foreach (var route in routes)
            {
                var routeName = CreateRouteName(routeSpec);
                if (routeName.HasValue())
                {
                    route.RouteName = routeName;
                    route.DataTokens.Add("routeName", routeName);
                }

                route.QueryStringConstraints = queryStringConstraints;
                route.QueryStringDefaults = queryStringDefaults;
                route.Translations = CreateRouteTranslations(routeSpec);
                route.Subdomain = routeSpec.Subdomain;
                route.UseLowercaseRoute = routeSpec.UseLowercaseRoute;
                route.PreserveCaseForUrlParameters = routeSpec.PreserveCaseForUrlParameters;
                route.AppendTrailingSlash = routeSpec.AppendTrailingSlash;

                // Yield the default route first
                yield return route;

                // Then yield the translations
                if (route.Translations != null)
                {
                    foreach (var translation in route.Translations)
                    {
                        // Backreference the default route.
                        translation.SourceLanguageRoute = route;

                        yield return translation;
                    }
                }
            }
        }
        private string CreateRouteUrl(string routeUrl, string routePrefix, string areaUrl, IDictionary <string, object> defaults, RouteSpecification routeSpec)
        {
            var tokenizedUrl      = BuildTokenizedUrl(routeUrl, routePrefix, areaUrl, routeSpec);
            var tokenizedPath     = RemoveQueryString(tokenizedUrl);
            var detokenizedPath   = DetokenizeUrl(tokenizedPath);
            var urlParameterNames = GetUrlParameterContents(detokenizedPath).ToList();

            var urlBuilder = new StringBuilder(detokenizedPath);

            // Replace {controller} URL param with default value.
            if (urlParameterNames.Any(n => n.ValueEquals("controller")))
            {
                urlBuilder.Replace("{controller}", (string)defaults["controller"]);
            }

            // Replace {action} URL param with default value.
            if (urlParameterNames.Any(n => n.ValueEquals("action")))
            {
                urlBuilder.Replace("{action}", (string)defaults["action"]);
            }

            // Explicitly defined area routes are not valid
            if (urlParameterNames.Any(n => n.ValueEquals("area")))
            {
                throw new AttributeRoutingException(
                          "{area} url parameters are not allowed. Specify the area name by using the RouteAreaAttribute.");
            }

            // If we are lowercasing routes, then lowercase everything but the route params
            var lower = routeSpec.UseLowercaseRoute.GetValueOrDefault(_configuration.UseLowercaseRoutes);

            if (lower)
            {
                for (var i = 0; i < urlBuilder.Length; i++)
                {
                    var c = urlBuilder[i];
                    if (Char.IsUpper(c))
                    {
                        urlBuilder[i] = Char.ToLower(c);
                    }
                    else if (c == '{')
                    {
                        while (urlBuilder[i] != '}' && i < urlBuilder.Length)
                        {
                            i++;
                        }
                    }
                }
            }

            return(urlBuilder.ToString().Trim('/'));
        }
        private string BuildTokenizedUrl(string routeUrl, string routePrefixUrl, string areaUrl, RouteSpecification routeSpec)
        {
            var delimitedUrl = routeUrl + "/";

            // Prepend prefix if available
            if (routePrefixUrl.HasValue() && !routeSpec.IgnoreRoutePrefix)
            {
                var delimitedRoutePrefix = routePrefixUrl + "/";
                if (!delimitedUrl.StartsWith(delimitedRoutePrefix))
                {
                    delimitedUrl = delimitedRoutePrefix + delimitedUrl;
                }
            }

            // Prepend area url if available
            if (areaUrl.HasValue() && !routeSpec.IgnoreAreaUrl)
            {
                var delimitedAreaUrl = areaUrl + "/";
                if (!delimitedUrl.StartsWith(delimitedAreaUrl))
                {
                    delimitedUrl = delimitedAreaUrl + delimitedUrl;
                }
            }

            return(delimitedUrl.Trim('/'));
        }
Exemplo n.º 42
0
        private string CreateRouteName(RouteSpecification routeSpec)
        {
            if (routeSpec.RouteName.HasValue())
                return routeSpec.RouteName;

            if (_configuration.AutoGenerateRouteNames)
            {
                var area = (routeSpec.AreaName.HasValue()) ? routeSpec.AreaName + "_" : null;
                return "{0}{1}_{2}".FormatWith(area, routeSpec.ControllerName, routeSpec.ActionName);
            }

            return null;
        }
        private IEnumerable<IAttributeRoute> CreateRouteTranslations(RouteSpecification routeSpec)
        {
            // If no translation provider, then get out of here.
            if (!_configuration.TranslationProviders.Any())
                yield break;

            // Merge all the culture names from the various providers.
            var cultureNames = _configuration.GetTranslationProviderCultureNames();

            // Built the route translations,
            // choosing the first available translated route component from among the providers
            foreach (var cultureName in cultureNames)
            {
                string translatedRouteUrl = null,
                       translatedRoutePrefix = null,
                       translatedAreaUrl = null;

                foreach (var provider in _configuration.TranslationProviders)
                {
                    translatedRouteUrl = translatedRouteUrl ?? provider.TranslateRouteUrl(cultureName, routeSpec);
                    translatedRoutePrefix = translatedRoutePrefix ?? provider.TranslateRoutePrefix(cultureName, routeSpec);
                    translatedAreaUrl = translatedAreaUrl ?? provider.TranslateAreaUrl(cultureName, routeSpec);
                }

                // If nothing is translated, then bail.
                if (translatedRouteUrl == null && translatedRoutePrefix == null && translatedAreaUrl == null)
                    continue;

                //*********************************************
                // Otherwise, build a translated route

                var routeUrl = CreateRouteUrl(translatedRouteUrl ?? routeSpec.RouteUrl,
                                              translatedRoutePrefix ?? routeSpec.RoutePrefixUrl,
                                              translatedAreaUrl ?? routeSpec.AreaUrl,
                                              routeSpec.IsAbsoluteUrl,
                                              routeSpec.UseLowercaseRoute);

                var translatedRoute = _routeFactory.CreateAttributeRoute(routeUrl,
                                                                         CreateRouteDefaults(routeSpec),
                                                                         CreateRouteConstraints(routeSpec),
                                                                         CreateRouteDataTokens(routeSpec));

                var routeName = CreateRouteName(routeSpec);
                if (routeName != null)
                {
                    translatedRoute.RouteName = routeName;
                    translatedRoute.DataTokens.Add("routeName", routeName);
                }

                translatedRoute.CultureName = cultureName;
                translatedRoute.DataTokens.Add("cultureName", cultureName);

                yield return translatedRoute;
            }
        }
        private IEnumerable <IAttributeRoute> CreateRouteTranslations(RouteSpecification routeSpec)
        {
            // If no translation provider, then get out of here.
            if (!_configuration.TranslationProviders.Any())
            {
                yield break;
            }

            // Merge all the culture names from the various providers.
            var cultureNames = _configuration.GetTranslationProviderCultureNames();

            // Built the route translations,
            // choosing the first available translated route component from among the providers
            foreach (var cultureName in cultureNames)
            {
                string translatedRouteUrl      = null,
                         translatedRoutePrefix = null,
                         translatedAreaUrl     = null;

                foreach (var provider in _configuration.TranslationProviders)
                {
                    translatedRouteUrl    = translatedRouteUrl ?? provider.TranslateRouteUrl(cultureName, routeSpec);
                    translatedRoutePrefix = translatedRoutePrefix ?? provider.TranslateRoutePrefix(cultureName, routeSpec);
                    translatedAreaUrl     = translatedAreaUrl ?? provider.TranslateAreaUrl(cultureName, routeSpec);
                }

                // If nothing is translated, then bail.
                if (translatedRouteUrl == null && translatedRoutePrefix == null && translatedAreaUrl == null)
                {
                    continue;
                }

                //*********************************************
                // Otherwise, build a translated route

                // REVIEW: Could probably forgo processing defaults, constraints, and data tokens for translated routes.

                IDictionary <string, object> defaults;
                IDictionary <string, object> queryStringDefaults;
                CreateRouteDefaults(routeSpec, out defaults, out queryStringDefaults);
                IDictionary <string, object> constraints;
                IDictionary <string, object> queryStringConstraints;
                CreateRouteConstraints(routeSpec, out constraints, out queryStringConstraints);
                var dataTokens = CreateRouteDataTokens(routeSpec);
                var routeUrl   = CreateRouteUrl(translatedRouteUrl ?? routeSpec.RouteUrl,
                                                translatedRoutePrefix ?? routeSpec.RoutePrefixUrl,
                                                translatedAreaUrl ?? routeSpec.AreaUrl,
                                                defaults,
                                                routeSpec);

                var translatedRoutes = _routeFactory.CreateAttributeRoutes(routeUrl, defaults, constraints, dataTokens);

                foreach (var translatedRoute in translatedRoutes)
                {
                    var routeName = CreateRouteName(routeSpec);
                    if (routeName != null)
                    {
                        translatedRoute.RouteName = routeName;
                        translatedRoute.DataTokens.Add("routeName", routeName);
                    }

                    translatedRoute.QueryStringConstraints = queryStringConstraints;
                    translatedRoute.QueryStringDefaults    = queryStringDefaults;
                    translatedRoute.CultureName            = cultureName;
                    translatedRoute.DataTokens.Add("cultureName", cultureName);

                    yield return(translatedRoute);
                }
            }
        }
Exemplo n.º 45
0
        private string BuildTokenizedUrl(string routeUrl, string routePrefixUrl, string areaUrl, SemanticVersion versionPrefix, RouteSpecification routeSpec)
        {
            var delimitedUrl = routeUrl + "/";

            // Prepend prefix if available
            if (routePrefixUrl.HasValue() && !routeSpec.IgnoreRoutePrefix)
            {
                var delimitedRoutePrefix = routePrefixUrl + "/";
                if (!delimitedUrl.StartsWith(delimitedRoutePrefix))
                    delimitedUrl = delimitedRoutePrefix + delimitedUrl;
            }

            if (versionPrefix != null)
            {
                var delimitedVerisonPrefix = versionPrefix.ToString() + "/";
                if (!delimitedUrl.StartsWith(delimitedVerisonPrefix))
                    delimitedUrl = delimitedVerisonPrefix + delimitedUrl;
            }

            // Prepend area url if available
            if (areaUrl.HasValue() && !routeSpec.IgnoreAreaUrl)
            {
                var delimitedAreaUrl = areaUrl + "/";
                if (!delimitedUrl.StartsWith(delimitedAreaUrl))
                    delimitedUrl = delimitedAreaUrl + delimitedUrl;
            }

            return delimitedUrl.Trim('/');
        }
Exemplo n.º 46
0
        private RouteValueDictionary CreateRouteDataTokens(RouteSpecification routeSpec)
        {
            var dataTokens = new RouteValueDictionary
            {
                { "namespaces", new[] { routeSpec.ControllerType.Namespace } }
            };

            if (routeSpec.AreaName.HasValue())
            {
                dataTokens.Add("area", routeSpec.AreaName);
                dataTokens.Add("UseNamespaceFallback", false);
            }

            return dataTokens;
        }
Exemplo n.º 47
0
        private RouteValueDictionary CreateRouteConstraints(RouteSpecification routeSpec)
        {
            var constraints = new RouteValueDictionary();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
                constraints.Add("httpMethod", new RestfulHttpMethodConstraint(routeSpec.HttpMethods));

            // Inline constraints
            foreach (var parameter in GetUrlParameterContents(routeSpec.RouteUrl).Where(p => p.Contains(":")).Select(p => p.Trim('?')))
            {
                var indexOfColumn = parameter.IndexOf(':');
                var parameterName = parameter.Substring(0, indexOfColumn);

                if (constraints.ContainsKey(parameterName))
                    continue;

                var constraintDefinition = parameter.Substring(indexOfColumn + 1, parameter.Length - indexOfColumn - 1);
                if (constraintDefinition.Contains('='))
                    constraintDefinition = constraintDefinition.Substring(0, constraintDefinition.IndexOf('='));

                IRouteConstraint constraint;

                if (Regex.IsMatch(constraintDefinition, @"^.*\(.*\)$"))
                {
                    // Constraint of the form "firstName:string(50)"
                    var indexOfOpenParen = constraintDefinition.IndexOf('(');
                    var constraintType = constraintDefinition.Substring(0, indexOfOpenParen);
                    var constraintParams = constraintDefinition.Substring(indexOfOpenParen + 1, constraintDefinition.Length - indexOfOpenParen - 2);
                    constraint = RouteConstraintFactory.GetConstraint(constraintType, constraintParams.SplitAndTrim(new[] { "/" }));
                }
                else
                    // Constraint of the form "id:int"
                    constraint = RouteConstraintFactory.GetConstraint(constraintDefinition);

                constraints.Add(parameterName, constraint);
            }

            // Attribute-based constraints
            foreach (var constraintAttribute in routeSpec.ConstraintAttributes)
            {
                if (constraints.ContainsKey(constraintAttribute.Key))
                    continue;

                constraints.Add(constraintAttribute.Key, constraintAttribute.Constraint);
            }

            var detokenizedUrl = DetokenizeUrl(CreateRouteUrl(routeSpec));
            var urlParameterNames = GetUrlParameterContents(detokenizedUrl);

            // Convention-based constraints
            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;

                foreach (var urlParameterName in urlParameterNames.Where(n => Regex.IsMatch(n, pattern)))
                {
                    if (constraints.ContainsKey(urlParameterName))
                        continue;

                    constraints.Add(urlParameterName, defaultConstraint.Value);
                }
            }

            return constraints;
        }
        private IDictionary<string, object> CreateRouteConstraints(RouteSpecification routeSpec)
        {
            var constraints = new Dictionary<string, object>();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
                constraints.Add("httpMethod", _routeConstraintFactory.CreateRestfulHttpMethodConstraint(routeSpec.HttpMethods));

            // Work from a complete, tokenized url; ie: support constraints in area urls, route prefix urls, and route urls.
            var tokenizedUrl = BuildTokenizedUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec.IsAbsoluteUrl);
            var urlParameters = GetUrlParameterContents(tokenizedUrl).ToList();

            // Inline constraints
            var constraintFactory = _configuration.RouteConstraintFactory;
            foreach (var parameter in urlParameters.Where(p => p.Contains(":")))
            {
                // Keep track of whether this param is optional,
                // because we wrap the final constraint if so.
                var parameterIsOptional = parameter.EndsWith("?");

                // Strip off everything related to defaults.
                var cleanParameter = parameter.TrimEnd('?').Split('=').FirstOrDefault();

                var sections = cleanParameter.SplitAndTrim(":");
                var parameterName = sections.First();

                // Do not override default or legacy inline constraints
                if (constraints.ContainsKey(parameterName))
                    continue;

                // Add constraints for each inline definition
                var inlineConstraints = new List<object>();
                var constraintDefinitions = sections.Skip(1);
                foreach (var definition in constraintDefinitions)
                {
                    string constraintName;
                    object constraint;

                    if (Regex.IsMatch(definition, @"^.*\(.*\)$"))
                    {
                        // Constraint of the form "firstName:string(50)"
                        var indexOfOpenParen = definition.IndexOf('(');
                        constraintName = definition.Substring(0, indexOfOpenParen);
                        var constraintParams = definition.Substring(indexOfOpenParen + 1, definition.Length - indexOfOpenParen - 2).SplitAndTrim(",");
                        constraint = constraintFactory.CreateInlineRouteConstraint(constraintName, constraintParams);
                    }
                    else
                    {
                        // Constraint of the form "id:int"
                        constraintName = definition;
                        constraint = constraintFactory.CreateInlineRouteConstraint(constraintName);
                    }

                    if (constraint == null)
                        throw new AttributeRoutingException(
                            "Could not find an available inline constraint for \"{0}\".".FormatWith(constraintName));

                    inlineConstraints.Add(constraint);
                }

                // Apply the constraint to the parameter.
                // Wrap multiple constraints in a compound constraint wrapper.
                // Wrap constraints for optional params in an optional constraint wrapper.
                var finalConstraint = (inlineConstraints.Count == 1)
                                          ? inlineConstraints.Single()
                                          : constraintFactory.CreateCompoundRouteConstraint(inlineConstraints.ToArray());

                if (parameterIsOptional)
                    constraints.Add(parameterName, constraintFactory.CreateOptionalRouteConstraint(finalConstraint));
                else
                    constraints.Add(parameterName, finalConstraint);
            }

            // Globally configured constraints
            var detokenizedPrefixedUrl = DetokenizeUrl(tokenizedUrl);
            var urlParameterNames = GetUrlParameterContents(detokenizedPrefixedUrl).ToList();
            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;

                foreach (var urlParameterName in urlParameterNames.Where(n => Regex.IsMatch(n, pattern)))
                {
                    if (constraints.ContainsKey(urlParameterName))
                        continue;

                    constraints.Add(urlParameterName, defaultConstraint.Value);
                }
            }

            return constraints;
        }
Exemplo n.º 49
0
        private RouteValueDictionary CreateRouteDefaults(RouteSpecification routeSpec)
        {
            var defaults = new RouteValueDictionary
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };

            var urlParameters = GetUrlParameterContents(routeSpec.RouteUrl);

            // Inspect the url for optional parameters, specified with a leading or trailing (or both) ?
            foreach (var parameter in urlParameters.Where(p => p.StartsWith("?") || p.EndsWith("?")))
            {
                var parameterName = parameter.Trim('?');

                if (parameterName.Contains(':'))
                    parameterName = parameterName.Substring(0, parameterName.IndexOf(':'));

                if (defaults.ContainsKey(parameterName))
                    continue;

                defaults.Add(parameterName, UrlParameter.Optional);
            }

            // Inline defaults
            foreach (var parameter in urlParameters.Where(p => p.Contains('=')))
            {
                var indexOfEquals = parameter.IndexOf('=');
                var parameterName = parameter.Substring(0, indexOfEquals);

                if (parameterName.Contains(':'))
                    parameterName = parameterName.Substring(0, parameterName.IndexOf(':'));

                if (defaults.ContainsKey(parameterName))
                    continue;

                var defaultValue = parameter.Substring(indexOfEquals + 1, parameter.Length - indexOfEquals - 1);
                defaults.Add(parameterName, defaultValue);
            }

            // Attribute-based defaults
            foreach (var defaultAttribute in routeSpec.DefaultAttributes)
            {
                if (defaults.ContainsKey(defaultAttribute.Key))
                    continue;

                defaults.Add(defaultAttribute.Key, defaultAttribute.Value);
            }

            return defaults;
        }
        private IEnumerable<IAttributeRoute> Build(RouteSpecification routeSpec)
        {
            var route = _routeFactory.CreateAttributeRoute(CreateRouteUrl(routeSpec),
                                                           CreateRouteDefaults(routeSpec),
                                                           CreateRouteConstraints(routeSpec),
                                                           CreateRouteDataTokens(routeSpec));

            var routeName = CreateRouteName(routeSpec);
            if (routeName.HasValue())
            {
                route.RouteName = routeName;
                route.DataTokens.Add("routeName", routeName);
            }

            route.Translations = CreateRouteTranslations(routeSpec);
            route.Subdomain = routeSpec.Subdomain;
            route.UseLowercaseRoute = routeSpec.UseLowercaseRoute;
            route.PreserveCaseForUrlParameters = routeSpec.PreserveCaseForUrlParameters;
            route.AppendTrailingSlash = routeSpec.AppendTrailingSlash;

            // Yield the default route first
            yield return route;

            // Then yield the translations
            if (route.Translations == null)
                yield break;

            foreach (var translation in route.Translations)
            {
                // Backreference the default route.
                translation.DefaultRouteContainer = route;

                yield return translation;
            }
        }
Exemplo n.º 51
0
        private IEnumerable<AttributeRoute> CreateRouteTranslations(RouteSpecification routeSpec)
        {
            // If no translation provider, then get out of here.
            if (!_configuration.TranslationProviders.Any())
                yield break;

            // Merge all the culture names from the various providers.
            var cultureNames = _configuration.GetTranslationProviderCultureNames();

            // Built the route translations,
            // choosing the first available translated route component from among the providers
            foreach (var cultureName in cultureNames)
            {
                string translatedRouteUrl = null,
                       translatedRoutePrefix = null,
                       translatedAreaUrl = null;

                foreach (var provider in _configuration.TranslationProviders)
                {
                    translatedRouteUrl = translatedRouteUrl ?? provider.TranslateRouteUrl(cultureName, routeSpec);
                    translatedRoutePrefix = translatedRoutePrefix ?? provider.TranslateRoutePrefix(cultureName, routeSpec);
                    translatedAreaUrl = translatedAreaUrl ?? provider.TranslateAreaUrl(cultureName, routeSpec);
                }

                if (translatedRouteUrl == null && translatedRoutePrefix == null && translatedAreaUrl == null)
                    continue;

                var translatedRoute =
                    new AttributeRoute(CreateRouteUrl(translatedRouteUrl ?? routeSpec.RouteUrl,
                                                      translatedRoutePrefix ?? routeSpec.RoutePrefixUrl,
                                                      translatedAreaUrl ?? routeSpec.AreaUrl,
                                                      routeSpec.IsAbsoluteUrl),
                                       CreateRouteDefaults(routeSpec),
                                       CreateRouteConstraints(routeSpec),
                                       CreateRouteDataTokens(routeSpec),
                                       _configuration)
                    {
                        CultureName = cultureName,
                    };

                translatedRoute.DataTokens.Add("cultureName", cultureName);

                yield return translatedRoute;
            }
        }
Exemplo n.º 52
0
        private IDictionary<string, object> CreateRouteConstraints(RouteSpecification routeSpec)
        {
            var constraints = new Dictionary<string, object>();

            // Default constraints
            if (routeSpec.HttpMethods.Any())
                constraints.Add("inboundHttpMethod", _routeConstraintFactory.CreateInboundHttpMethodConstraint(routeSpec.HttpMethods));

            // Work from a complete, tokenized url; ie: support constraints in area urls, route prefix urls, and route urls.
            var tokenizedUrl = BuildTokenizedUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec);
            var urlParameters = GetUrlParameterContents(tokenizedUrl).ToList();

            // Need to keep track of query params.
            // Can do this by detokenizing URL (which strips query),
            // and then taking all the URL parameters except those from the path part of the URL.
            var pathOnlyUrl = RemoveQueryString(tokenizedUrl);
            var pathOnlyUrlParameters = GetUrlParameterContents(pathOnlyUrl);
            var queryStringParameters = urlParameters.Except(pathOnlyUrlParameters).ToList();

            // Inline constraints
            foreach (var parameter in urlParameters)
            {
                // Keep track of whether this param is optional or in the querystring,
                // because we wrap the final constraint if so.
                var parameterIsOptional = parameter.EndsWith("?");
                var parameterIsInQueryString = queryStringParameters.Contains(parameter);

                // If this is a path parameter and doesn't have a constraint, then skip it.
                if (!parameterIsInQueryString && !parameter.Contains(":"))
                    continue;

                // Strip off everything related to defaults.
                var cleanParameter = parameter.TrimEnd('?').Split('=').FirstOrDefault();

                var sections = cleanParameter.SplitAndTrim(":");
                var parameterName = sections.First();

                // Do not override default or legacy inline constraints
                if (constraints.ContainsKey(parameterName))
                    continue;

                // Add constraints for each inline definition
                var inlineConstraints = new List<object>();
                var constraintDefinitions = sections.Skip(1);
                foreach (var definition in constraintDefinitions)
                {
                    string constraintName;
                    object constraint;

                    if (Regex.IsMatch(definition, @"^.*\(.*\)$"))
                    {
                        // Constraint of the form "firstName:string(50)"
                        var indexOfOpenParen = definition.IndexOf('(');
                        constraintName = definition.Substring(0, indexOfOpenParen);

                        // Parse constraint params.
                        // NOTE: Splitting on commas only applies to non-regex constraints.
                        var constraintParamsRaw = definition.Substring(indexOfOpenParen + 1, definition.Length - indexOfOpenParen - 2);
                        var constraintParams = constraintName.ValueEquals("regex")
                                                   ? new[] {constraintParamsRaw}
                                                   : constraintParamsRaw.SplitAndTrim(",");

                        constraint = _routeConstraintFactory.CreateInlineRouteConstraint(constraintName, constraintParams);
                    }
                    else
                    {
                        // Constraint of the form "id:int"
                        constraintName = definition;
                        constraint = _routeConstraintFactory.CreateInlineRouteConstraint(constraintName);
                    }

                    if (constraint == null)
                        throw new AttributeRoutingException(
                            "Could not find an available inline constraint for \"{0}\".".FormatWith(constraintName));

                    inlineConstraints.Add(constraint);
                }

                // Apply the constraint to the parameter, and wrap constraints in the following priority:
                object finalConstraint;

                // 1. If more than one constraint, wrap in a compound constraint.
                if (inlineConstraints.Count > 1)
                {
                    finalConstraint = _routeConstraintFactory.CreateCompoundRouteConstraint(inlineConstraints.ToArray());
                }
                else
                {
                    finalConstraint = inlineConstraints.FirstOrDefault();
                }

                // 2. If the constraint is in the querystring, wrap in a query string constraint.
                if (parameterIsInQueryString)
                {
                    finalConstraint = _routeConstraintFactory.CreateQueryStringRouteConstraint(finalConstraint);
                }

                // 3. If the constraint is optional, wrap in an optional constraint.
                if (parameterIsOptional)
                {
                    finalConstraint = _routeConstraintFactory.CreateOptionalRouteConstraint(finalConstraint);
                }

                constraints.Add(parameterName, finalConstraint);

            } // ... go to next parameter

            // Globally configured constraints
            var detokenizedPrefixedUrl = DetokenizeUrl(tokenizedUrl);
            var urlParameterNames = GetUrlParameterContents(detokenizedPrefixedUrl).ToList();
            foreach (var defaultConstraint in _configuration.DefaultRouteConstraints)
            {
                var pattern = defaultConstraint.Key;

                foreach (var urlParameterName in urlParameterNames.Where(n => Regex.IsMatch(n, pattern)))
                {
                    if (constraints.ContainsKey(urlParameterName))
                        continue;

                    constraints.Add(urlParameterName, defaultConstraint.Value);
                }
            }

            return constraints;
        }
Exemplo n.º 53
0
 private string CreateRouteUrl(RouteSpecification routeSpec)
 {
     return CreateRouteUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec.IsAbsoluteUrl);
 }
Exemplo n.º 54
0
        private void CreateRouteDefaults(RouteSpecification routeSpec, out IDictionary<string, object> defaults, out IDictionary<string, object> queryStringDefaults)
        {
            // Going to return individual collections for:
            // - path routes defaults (which will go into the generated route's Defaults prop),
            // - and query string route defaults (which will not work perfectly with the MS bits, and need special treatment by IAttributeRoute impls).
            defaults = new Dictionary<string, object>
            {
                { "controller", routeSpec.ControllerName },
                { "action", routeSpec.ActionName }
            };
            queryStringDefaults = new Dictionary<string, object>();

            // Work from a complete, tokenized url; ie: support constraints in area urls, route prefix urls, and route urls.
            var tokenizedUrl = BuildTokenizedUrl(routeSpec.RouteUrl, routeSpec.RoutePrefixUrl, routeSpec.AreaUrl, routeSpec);
            var urlParameters = GetUrlParameterContents(tokenizedUrl).ToList();

            // Need to keep track of which are path and query params.
            var pathOnlyUrl = RemoveQueryString(tokenizedUrl);
            var pathOnlyUrlParameters = GetUrlParameterContents(pathOnlyUrl).ToList();
            var queryStringParameters = urlParameters.Except(pathOnlyUrlParameters).ToList();

            // Inspect the url path for optional parameters and default values.
            foreach (var parameter in urlParameters)
            {
                // Does this param have a default value or is it optional?
                var isOptional = parameter.EndsWith("?");
                var indexOfEquals = parameter.IndexOf('=');
                if (!isOptional && indexOfEquals == -1)
                {
                    continue;
                }

                // Keep track if this is a querystring param
                var parameterIsInQueryString = queryStringParameters.Contains(parameter);

                // Strip off inline constraints, defaults, and optional tokens.
                var parameterName = DetokenizeUrlParamContentsRegex.Replace(parameter, "");

                // Do not override default defaults.
                if (defaults.ContainsKey(parameterName))
                {
                    continue;
                }

                object defaultValue;
                if (isOptional)
                {
                    defaultValue = _parameterFactory.Optional();
                }
                else // It has a default value.
                {
                    defaultValue = parameter.Substring(indexOfEquals + 1, parameter.Length - indexOfEquals - 1);
                }

                if (parameterIsInQueryString)
                {
                    queryStringDefaults.Add(parameterName, defaultValue);
                }
                else
                {
                    defaults.Add(parameterName, defaultValue);
                }
            }
        }
Exemplo n.º 55
0
        private string BuildTokenizedUrl(string routeUrl, string routePrefixUrl, string areaUrl, RouteSpecification routeSpec)
        {
            var delimitedUrl = routeUrl + "/";

            // Prepend prefix if available
            if (routePrefixUrl.HasValue() && !routeSpec.IgnoreRoutePrefix)
            {
                var delimitedRoutePrefix = routePrefixUrl + "/";
                if (!delimitedUrl.StartsWith(delimitedRoutePrefix))
                {
                    delimitedUrl = delimitedRoutePrefix + delimitedUrl;
                }
            }

            // Prepend area url if available
            if (areaUrl.HasValue() && !routeSpec.IgnoreAreaUrl)
            {
                var delimitedAreaUrl = areaUrl + "/";
                if (!delimitedUrl.StartsWith(delimitedAreaUrl))
                {
                    delimitedUrl = delimitedAreaUrl + delimitedUrl;
                }
            }

            return delimitedUrl.Trim('/');
        }