private BoundUrl BuildUrl(ValueDictionary defaults, ValueDictionary acceptedValues, HashSet <string> unusedValues) { StringBuilder pathBuilder = new StringBuilder(); StringBuilder segmentBuilder = new StringBuilder(); bool flush = false; foreach (PathSegment segment in _segments) { SeparatorSegment separator = (segment as SeparatorSegment); ContentSegment content = (segment as ContentSegment); if (separator != null) { if (flush && segmentBuilder.Length > 0) { pathBuilder.Append(segmentBuilder.ToString()); segmentBuilder.Length = 0; } flush = false; segmentBuilder.Append(RouteParser.PathSeparator); } if (content != null) { bool segmentEnd = false; foreach (PathSubsegment subsegment in content.Segments) { LiteralSubsegment literal = (subsegment as LiteralSubsegment); ParameterSubsegment parameter = (subsegment as ParameterSubsegment); if (literal != null) { flush = true; segmentBuilder.Append(Uri.EscapeUriString(literal.Literal)); } if (parameter != null) { object acceptedValue; object defaultValue; if (flush && segmentBuilder.Length > 0) { pathBuilder.Append(segmentBuilder.ToString()); segmentBuilder.Length = 0; segmentEnd = true; } flush = false; if (acceptedValues.TryGetValue(parameter.ParameterName, out acceptedValue)) { unusedValues.Remove(parameter.ParameterName); } defaults.TryGetValue(parameter.ParameterName, out defaultValue); if (RoutePartsEqual(acceptedValue, defaultValue)) { segmentBuilder.Append(Uri.EscapeUriString( Convert.ToString(acceptedValue, CultureInfo.InvariantCulture))); continue; } if (segmentBuilder.Length > 0) { pathBuilder.Append(segmentBuilder.ToString()); segmentBuilder.Length = 0; } pathBuilder.Append(Uri.EscapeUriString(Convert.ToString(acceptedValue, CultureInfo.InvariantCulture))); segmentEnd = true; } } if (segmentEnd && segmentBuilder.Length > 0) { pathBuilder.Append(segmentBuilder.ToString()); segmentBuilder.Length = 0; } } } if (flush && segmentBuilder.Length > 0) { pathBuilder.Append(segmentBuilder.ToString()); } if (unusedValues.Count > 0) { bool isFirst = true; foreach (string key in unusedValues) { object value; if (acceptedValues.TryGetValue(key, out value)) { pathBuilder.Append(isFirst ? '?' : '&'); isFirst = false; pathBuilder.Append(Uri.EscapeDataString(key.ToLowerInvariant())); pathBuilder.Append('='); pathBuilder.Append(Uri.EscapeDataString( Convert.ToString(value, CultureInfo.InvariantCulture))); } } } return(new BoundUrl(pathBuilder.ToString(), acceptedValues)); }
public ValueDictionary Match(string virtualPath, ValueDictionary variables, ValueDictionary defaults) { List <string> parts = new List <string>(RouteParser.SplitUrl(virtualPath)); defaults = defaults ?? new ValueDictionary(); variables = variables ?? new ValueDictionary(); ValueDictionary values = new ValueDictionary(); bool hasAdditionalParameters = false; bool isCatchAll = false; AssignVariableValues(variables); for (int i = 0; i < _segments.Count; i++) { SeparatorSegment separator = (_segments[i] as SeparatorSegment); ContentSegment content = (_segments[i] as ContentSegment); if (parts.Count <= i) { hasAdditionalParameters = true; } string part = (hasAdditionalParameters) ? null : parts[i]; if (separator != null) { if (!hasAdditionalParameters && !RouteParser.IsSeparator(part)) { return(null); } } if (content != null) { if (content.IsCatchAll) { MatchCatchAll(content, parts.Skip(i), defaults, values); isCatchAll = true; } else if (!MatchContent(content, part, defaults, values)) { return(null); } } } if (!isCatchAll && _segments.Count < parts.Count) { for (int j = _segments.Count; j < parts.Count; j++) { if (!RouteParser.IsSeparator(parts[j])) { return(null); } } } if (defaults != null) { foreach (KeyValuePair <string, object> kvp in defaults) { if (!values.ContainsKey(kvp.Key)) { values.Add(kvp.Key, kvp.Value); } } } return(values); }