Beispiel #1
0
        public TemplateBinder(
            UrlEncoder urlEncoder,
            ObjectPool<UriBuildingContext> pool,
            RouteTemplate template,
            RouteValueDictionary defaults)
        {
            if (urlEncoder == null)
            {
                throw new ArgumentNullException(nameof(urlEncoder));
            }

            if (pool == null)
            {
                throw new ArgumentNullException(nameof(pool));
            }

            if (template == null)
            {
                throw new ArgumentNullException(nameof(template));
            }

            _urlEncoder = urlEncoder;
            _pool = pool;
            _template = template;
            _defaults = defaults;

            // Any default that doesn't have a corresponding parameter is a 'filter' and if a value
            // is provided for that 'filter' it must match the value in defaults.
            _filters = new RouteValueDictionary(_defaults);
            foreach (var parameter in _template.Parameters)
            {
                _filters.Remove(parameter.Name);
            }
        }
Beispiel #2
0
        public TemplateRoute(
            IRouter target,
            string routeName,
            string routeTemplate,
            IDictionary<string, object> defaults,
            IDictionary<string, object> constraints,
            IDictionary<string, object> dataTokens,
            IInlineConstraintResolver inlineConstraintResolver)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            _target = target;
            _routeTemplate = routeTemplate ?? string.Empty;
            Name = routeName;

            _dataTokens = dataTokens == null ? RouteValueDictionary.Empty : new RouteValueDictionary(dataTokens);

            // Data we parse from the template will be used to fill in the rest of the constraints or
            // defaults. The parser will throw for invalid routes.
            _parsedTemplate = TemplateParser.Parse(RouteTemplate);

            _constraints = GetConstraints(inlineConstraintResolver, RouteTemplate, _parsedTemplate, constraints);
            _defaults = GetDefaults(_parsedTemplate, defaults);

            _matcher = new TemplateMatcher(_parsedTemplate, Defaults);
            _binder = new TemplateBinder(_parsedTemplate, Defaults);
        }
		/// <summary>
		/// Parses the specified route template string, placing the available information in
		/// <see cref="info" />.
		/// </summary>
		/// <param name="template">Template to parse</param>
		/// <param name="info">RouteInfo to store parsed info</param>
		public void Parse(RouteTemplate template, RouteInfo info)
		{
			var builder = new StringBuilder();
			foreach (var segment in template.Segments)
			{
				foreach (var part in segment.Parts)
				{
					if (part.IsLiteral)
					{
						builder.Append(part.Text);
						continue;
					}
					if (part.DefaultValue != null)
					{
						info.Defaults[part.Name] = part.DefaultValue;
					}
					if (part.IsOptional)
					{
						info.Optional.Add(part.Name);
					}
					builder.Append('{');
					builder.Append(part.Name);
					builder.Append('}');

					// TODO part.IsOptionalSeperator
					// TODO part.IsCatchAll
				}
				builder.Append('/');
			}
			info.Url = builder.ToString().TrimEnd('/');
		}
Beispiel #4
0
        public TemplateBinder(RouteTemplate template, IReadOnlyDictionary<string, object> defaults)
        {
            if (template == null)
            {
                throw new ArgumentNullException(nameof(template));
            }

            _template = template;
            _defaults = defaults;
        }
Beispiel #5
0
        public TemplateMatcher(
            RouteTemplate template,
            IReadOnlyDictionary<string, object> defaults)
        {
            if (template == null)
            {
                throw new ArgumentNullException(nameof(template));
            }

            Template = template;
            Defaults = defaults ?? RouteValueDictionary.Empty;
        }
        public static decimal Compute(RouteTemplate template)
        {
            // Each precedence digit corresponds to one decimal place. For example, 3 segments with precedences 2, 1,
            // and 4 results in a combined precedence of 2.14 (decimal).
            var precedence = 0m;

            for (var i = 0; i < template.Segments.Count; i++)
            {
                var segment = template.Segments[i];

                var digit = ComputeDigit(segment);
                Debug.Assert(digit >= 0 && digit < 10);

                precedence += Decimal.Divide(digit, (decimal)Math.Pow(10, i));
            }

            return precedence;
        }
Beispiel #7
0
        public TemplateMatcher(
            RouteTemplate template,
            RouteValueDictionary defaults)
        {
            if (template == null)
            {
                throw new ArgumentNullException(nameof(template));
            }

            Template = template;
            Defaults = defaults ?? new RouteValueDictionary();

            // Perf: cache the default value for each parameter (other than complex segments).
            _hasDefaultValue = new bool[Template.Segments.Count];
            _defaultValues = new object[Template.Segments.Count];

            for (var i = 0; i < Template.Segments.Count; i++)
            {
                var segment = Template.Segments[i];
                if (!segment.IsSimple)
                {
                    continue;
                }

                var part = segment.Parts[0];
                if (!part.IsParameter)
                {
                    continue;
                }

                object value;
                if (Defaults.TryGetValue(part.Name, out value))
                {
                    _hasDefaultValue[i] = true;
                    _defaultValues[i] = value;
                }
            }
        }
Beispiel #8
0
        public TemplateRoute([NotNull] IRouter target,
                             string routeName,
                             string routeTemplate,
                             IDictionary <string, object> defaults,
                             IDictionary <string, object> constraints,
                             IDictionary <string, object> dataTokens,
                             IInlineConstraintResolver inlineConstraintResolver)
        {
            _target        = target;
            _routeTemplate = routeTemplate ?? string.Empty;
            Name           = routeName;
            _defaults      = defaults ?? new RouteValueDictionary();
            _constraints   = RouteConstraintBuilder.BuildConstraints(constraints, _routeTemplate) ??
                             new Dictionary <string, IRouteConstraint>();
            _dataTokens = dataTokens ?? new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);

            // The parser will throw for invalid routes.
            _parsedTemplate = TemplateParser.Parse(RouteTemplate, inlineConstraintResolver);
            UpdateInlineDefaultValuesAndConstraints();

            _matcher = new TemplateMatcher(_parsedTemplate);
            _binder  = new TemplateBinder(_parsedTemplate, _defaults);
        }
Beispiel #9
0
        public TemplateRoute([NotNull] IRouter target,
                             string routeName,
                             string routeTemplate,
                             IDictionary <string, object> defaults,
                             IDictionary <string, object> constraints,
                             IDictionary <string, object> dataTokens,
                             IInlineConstraintResolver inlineConstraintResolver)
        {
            _target        = target;
            _routeTemplate = routeTemplate ?? string.Empty;
            Name           = routeName;

            _dataTokens = dataTokens == null ? RouteValueDictionary.Empty : new RouteValueDictionary(dataTokens);

            // Data we parse from the template will be used to fill in the rest of the constraints or
            // defaults. The parser will throw for invalid routes.
            _parsedTemplate = TemplateParser.Parse(RouteTemplate);

            _constraints = GetConstraints(inlineConstraintResolver, RouteTemplate, _parsedTemplate, constraints);
            _defaults    = GetDefaults(_parsedTemplate, defaults);

            _matcher = new TemplateMatcher(_parsedTemplate, Defaults);
            _binder  = new TemplateBinder(_parsedTemplate, Defaults);
        }
        private static IReadOnlyDictionary<string, IRouteConstraint> GetRouteConstriants(
            IInlineConstraintResolver inlineConstraintResolver,
            string template,
            RouteTemplate parsedRouteTemplate)
        {
            var constraintBuilder = new RouteConstraintBuilder(inlineConstraintResolver, template);
            foreach (var parameter in parsedRouteTemplate.Parameters)
            {
                if (parameter.InlineConstraints != null)
                {
                    if (parameter.IsOptional)
                    {
                        constraintBuilder.SetOptional(parameter.Name);
                    }

                    foreach (var constraint in parameter.InlineConstraints)
                    {
                        constraintBuilder.AddResolvedConstraint(parameter.Name, constraint.Constraint);
                    }
                }
            }

            return constraintBuilder.Build();
        }
		/// <summary>
		/// Processes the defaults for the specified action.
		/// </summary>
		/// <param name="action">MVC action</param>
		/// <param name="template">Route template for this action</param>
		/// <returns>Defaults for this action</returns>
		private IDictionary<string, object> GetDefaults(ControllerActionDescriptor action, RouteTemplate template)
		{
			var defaults = template.Parameters
				.Where(p => p.DefaultValue != null)
				.ToDictionary(
					p => p.Name.ToLowerInvariant(),
					p => p.DefaultValue,
					StringComparer.OrdinalIgnoreCase
				);

			defaults.Add("controller", action.ControllerName);
			defaults.Add("action", action.Name);
			return defaults;
		}
		/// <summary>
		/// Processes the constraints for the specified template.
		/// </summary>
		/// <param name="rawTemplate">Raw template string</param>
		/// <param name="parsedTemplate">Parsed template</param>
		/// <returns>The constraints for this route</returns>
		private IDictionary<string, object> GetConstraints(string rawTemplate, RouteTemplate parsedTemplate)
		{
			var constraintBuilder = new RouteConstraintBuilder(_constraintResolver, rawTemplate);
			foreach (var parameter in parsedTemplate.Parameters)
			{
				if (parameter.InlineConstraints != null)
				{
					if (parameter.IsOptional)
					{
						constraintBuilder.SetOptional(parameter.Name);
					}

					foreach (var inlineConstraint in parameter.InlineConstraints)
					{
						constraintBuilder.AddResolvedConstraint(parameter.Name, inlineConstraint.Constraint);
					}
				}
			}

			var constraints = constraintBuilder.Build();
			return _constraintsProcessor.ProcessConstraints(constraints);
		}
Beispiel #13
0
 public TemplateBinder([NotNull] RouteTemplate template, IReadOnlyDictionary <string, object> defaults)
 {
     _template = template;
     _defaults = defaults;
 }
Beispiel #14
0
        protected static RouteValueDictionary GetDefaults(
            RouteTemplate parsedTemplate,
            RouteValueDictionary defaults)
        {
            var result = defaults == null ? new RouteValueDictionary() : new RouteValueDictionary(defaults);

            foreach (var parameter in parsedTemplate.Parameters)
            {
                if (parameter.DefaultValue != null)
                {
                    if (result.ContainsKey(parameter.Name))
                    {
                        throw new InvalidOperationException(
                          Resources.FormatTemplateRoute_CannotHaveDefaultValueSpecifiedInlineAndExplicitly(
                              parameter.Name));
                    }
                    else
                    {
                        result.Add(parameter.Name, parameter.DefaultValue);
                    }
                }
            }

            return result;
        }
Beispiel #15
0
        private static RouteValueDictionary GetDefaults(
            RouteTemplate parsedTemplate,
            IDictionary<string, object> defaults)
        {
            // Do not use RouteValueDictionary.Empty for defaults, it might be modified inside
            // UpdateInlineDefaultValuesAndConstraints()
            var result = defaults == null ? new RouteValueDictionary() : new RouteValueDictionary(defaults);

            foreach (var parameter in parsedTemplate.Parameters)
            {
                if (parameter.DefaultValue != null)
                {
                    if (result.ContainsKey(parameter.Name))
                    {
                        throw new InvalidOperationException(
                          Resources.FormatTemplateRoute_CannotHaveDefaultValueSpecifiedInlineAndExplicitly(
                              parameter.Name));
                    }
                    else
                    {
                        result.Add(parameter.Name, parameter.DefaultValue);
                    }
                }
            }

            return result;
        }
Beispiel #16
0
        private static IReadOnlyDictionary<string, IRouteConstraint> GetConstraints(
            IInlineConstraintResolver inlineConstraintResolver,
            string template,
            RouteTemplate parsedTemplate,
            IDictionary<string, object> constraints)
        {
            var constraintBuilder = new RouteConstraintBuilder(inlineConstraintResolver, template);

            if (constraints != null)
            {
                foreach (var kvp in constraints)
                {
                    constraintBuilder.AddConstraint(kvp.Key, kvp.Value);
                }
            }

            foreach (var parameter in parsedTemplate.Parameters)
            {
                if (parameter.IsOptional)
                {
                    constraintBuilder.SetOptional(parameter.Name);
                }

                foreach (var inlineConstraint in parameter.InlineConstraints)
                {
                    constraintBuilder.AddResolvedConstraint(parameter.Name, inlineConstraint.Constraint);
                }
            }

            return constraintBuilder.Build();
        }
Beispiel #17
0
 public TemplateBinder([NotNull] RouteTemplate template, IReadOnlyDictionary<string, object> defaults)
 {
     _template = template;
     _defaults = defaults;
 }