public static decimal Compute(TParsedRoute parsedRoute, IDictionary <string, object> constraints) { // 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). IList <PathContentSegment> segments = parsedRoute.PathSegments.OfType <PathContentSegment>().ToArray(); decimal precedence = 0; uint divisor = 1; // The first digit occupies the one's place. for (int i = 0; i < segments.Count; i++) { PathContentSegment segment = segments[i]; int digit = ComputeDigit(segment, constraints); Contract.Assert(digit >= 0 && digit < 10); precedence = precedence + Decimal.Divide(digit, divisor); // The next digit occupies the subsequent place (always after the decimal point and growing to the // right). divisor *= 10; } return(precedence); }
private static void AddUndeclaredRouteParameters(HttpParsedRoute parsedRoute, IDictionary <string, object> routeDefaults, IList <ApiParameterDescription> parameterDescriptions) { foreach (PathSegment path in parsedRoute.PathSegments) { PathContentSegment content = path as PathContentSegment; if (content != null) { foreach (PathSubsegment subSegment in content.Subsegments) { PathParameterSubsegment parameter = subSegment as PathParameterSubsegment; if (parameter != null) { object parameterValue; string parameterName = parameter.ParameterName; if (!parameterDescriptions.Any(p => String.Equals(p.Name, parameterName, StringComparison.OrdinalIgnoreCase)) && (!routeDefaults.TryGetValue(parameterName, out parameterValue) || parameterValue != RouteParameter.Optional)) { parameterDescriptions.Add( new ApiParameterDescription { Name = parameterName, Source = ApiParameterSource.FromUri }); } } } } } }
// Segments have the following order: // 1 - Literal segments // 2 - Constrained parameter segments / Multi-part segments // 3 - Unconstrained parameter segments // 4 - Constrained wildcard parameter segments // 5 - Unconstrained wildcard parameter segments internal static int ComputeDigit(PathContentSegment segment, IDictionary<string, object> constraints) { if (segment.Subsegments.Count > 1) { // Multi-part segments should appear after literal segments but before parameter segments return 2; } PathSubsegment subsegment = segment.Subsegments[0]; // Literal segments always go first if (subsegment is PathLiteralSubsegment) { return 1; } else { PathParameterSubsegment parameterSegment = subsegment as PathParameterSubsegment; Contract.Assert(parameterSegment != null); int order = parameterSegment.IsCatchAll ? 5 : 3; // If there is a route constraint for the parameter, reduce order by 1 // Constrained parameters end up with order 2, Constrained catch alls end up with order 4 if (constraints != null && constraints.ContainsKey(parameterSegment.ParameterName)) { order--; } return order; } }
// Segments have the following order: // 1 - Literal segments // 2 - Constrained parameter segments / Multi-part segments // 3 - Unconstrained parameter segments // 4 - Constrained wildcard parameter segments // 5 - Unconstrained wildcard parameter segments internal static int ComputeDigit(PathContentSegment segment, IDictionary <string, object> constraints) { if (segment.Subsegments.Count > 1) { // Multi-part segments should appear after literal segments but before parameter segments return(2); } PathSubsegment subsegment = segment.Subsegments[0]; // Literal segments always go first if (subsegment is PathLiteralSubsegment) { return(1); } else { PathParameterSubsegment parameterSegment = subsegment as PathParameterSubsegment; Contract.Assert(parameterSegment != null); int order = parameterSegment.IsCatchAll ? 5 : 3; // If there is a route constraint for the parameter, reduce order by 1 // Constrained parameters end up with order 2, Constrained catch alls end up with order 4 if (constraints != null && constraints.ContainsKey(parameterSegment.ParameterName)) { order--; } return(order); } }
// Default ordering goes through segments one by one and tries to apply an ordering private static int Compare(RouteEntry entry1, RouteEntry entry2) { ParsedRoute parsedRoute1 = entry1.ParsedRoute; ParsedRoute parsedRoute2 = entry2.ParsedRoute; IList <PathContentSegment> segments1 = parsedRoute1.PathSegments.OfType <PathContentSegment>().ToArray(); IList <PathContentSegment> segments2 = parsedRoute2.PathSegments.OfType <PathContentSegment>().ToArray(); for (int i = 0; i < segments1.Count && i < segments2.Count; i++) { PathContentSegment segment1 = segments1[i]; PathContentSegment segment2 = segments2[i]; int order1 = GetPrecedenceDigit(segment1, entry1.Route.Constraints); int order2 = GetPrecedenceDigit(segment2, entry2.Route.Constraints); if (order1 > order2) { return(1); } else if (order1 < order2) { return(-1); } } return(0); }
private static void MatchCatchAll(PathContentSegment contentPathSegment, IEnumerable <string> remainingRequestSegments, HttpRouteValueDictionary defaultValues, HttpRouteValueDictionary matchedValues) { object obj2; string str = string.Join(string.Empty, remainingRequestSegments.ToArray <string>()); PathParameterSubsegment subsegment = contentPathSegment.Subsegments[0] as PathParameterSubsegment; if (str.Length > 0) { obj2 = str; } else { defaultValues.TryGetValue(subsegment.ParameterName, out obj2); } matchedValues.Add(subsegment.ParameterName, obj2); }
// Default ordering goes through segments one by one and tries to apply an ordering private static int Compare(RouteEntry entry1, RouteEntry entry2) { ParsedRoute parsedRoute1 = entry1.ParsedRoute; ParsedRoute parsedRoute2 = entry2.ParsedRoute; IList <PathContentSegment> segments1 = parsedRoute1.PathSegments.OfType <PathContentSegment>().ToArray(); IList <PathContentSegment> segments2 = parsedRoute2.PathSegments.OfType <PathContentSegment>().ToArray(); for (int i = 0; i < segments1.Count && i < segments2.Count; i++) { PathContentSegment segment1 = segments1[i]; PathContentSegment segment2 = segments2[i]; int order1 = GetPrecedenceDigit(segment1, entry1.Route.Constraints); int order2 = GetPrecedenceDigit(segment2, entry2.Route.Constraints); if (order1 > order2) { return(1); } else if (order1 < order2) { return(-1); } } // Routes with constraints should come before the unconstrained routes, lest the unconstrained // routes claim too much. Method constraints are implemented as route constraints, so // if 2 routes are identical, place the one with method constraints first. if (entry1.HasVerbs) { if (entry2.HasVerbs) { return(0); } return(-1); } else { if (entry2.HasVerbs) { return(1); } return(0); } }
private static HttpRouteValueDictionary Match(RoutingContext context, HttpRouteValueDictionary defaultValues) { List <string> pathSegments = context.PathSegments; if (defaultValues == null) { defaultValues = new HttpRouteValueDictionary(); } HttpRouteValueDictionary matchedValues = new HttpRouteValueDictionary(); bool flag = false; bool flag2 = false; for (int i = 0; i < thisPathSegments.Count; i++) { PathSegment segment = thisPathSegments[i]; if (pathSegments.Count <= i) { flag = true; } string a = flag ? null : pathSegments[i]; if (segment is PathSeparatorSegment) { if (!flag && !string.Equals(a, "/", StringComparison.Ordinal)) { return(null); } } else { PathContentSegment contentPathSegment = segment as PathContentSegment; if (contentPathSegment != null) { if (contentPathSegment.IsCatchAll) { MatchCatchAll(contentPathSegment, pathSegments.Skip <string>(i), defaultValues, matchedValues); flag2 = true; } else if (!MatchContentPathSegment(contentPathSegment, a, defaultValues, matchedValues)) { return(null); } } } } if (!flag2 && (this.PathSegments.Count < pathSegments.Count)) { for (int j = thisPathSegments.Count; j < pathSegments.Count; j++) { if (!IsSeparator(pathSegments[j])) { return(null); } } } if (defaultValues != null) { foreach (KeyValuePair <string, object> pair in defaultValues) { if (!matchedValues.ContainsKey(pair.Key)) { matchedValues.Add(pair.Key, pair.Value); } } } return(matchedValues); }
private static bool MatchContentPathSegment(PathContentSegment routeSegment, string requestPathSegment, HttpRouteValueDictionary defaultValues, HttpRouteValueDictionary matchedValues) { if (string.IsNullOrEmpty(requestPathSegment)) { if (routeSegment.Subsegments.Count <= 1) { object obj2; PathParameterSubsegment subsegment3 = routeSegment.Subsegments[0] as PathParameterSubsegment; if (subsegment3 == null) { return(false); } if (defaultValues.TryGetValue(subsegment3.ParameterName, out obj2)) { matchedValues.Add(subsegment3.ParameterName, obj2); return(true); } } return(false); } if (routeSegment.Subsegments.Count == 1) { return(MatchSingleContentPathSegment(routeSegment.Subsegments[0], requestPathSegment, matchedValues)); } int length = requestPathSegment.Length; int num2 = routeSegment.Subsegments.Count - 1; PathParameterSubsegment subsegment = null; PathLiteralSubsegment subsegment2 = null; while (num2 >= 0) { int num3 = length; PathParameterSubsegment subsegment4 = routeSegment.Subsegments[num2] as PathParameterSubsegment; if (subsegment4 != null) { subsegment = subsegment4; } else { PathLiteralSubsegment subsegment5 = routeSegment.Subsegments[num2] as PathLiteralSubsegment; if (subsegment5 != null) { subsegment2 = subsegment5; int startIndex = length - 1; if (subsegment != null) { startIndex--; } if (startIndex < 0) { return(false); } int num5 = requestPathSegment.LastIndexOf(subsegment5.Literal, startIndex, StringComparison.OrdinalIgnoreCase); if (num5 == -1) { return(false); } if ((num2 == (routeSegment.Subsegments.Count - 1)) && ((num5 + subsegment5.Literal.Length) != requestPathSegment.Length)) { return(false); } num3 = num5; } } if ((subsegment != null) && (((subsegment2 != null) && (subsegment4 == null)) || (num2 == 0))) { int num6; int num7; if (subsegment2 == null) { if (num2 == 0) { num6 = 0; } else { num6 = num3; } num7 = length; } else if ((num2 == 0) && (subsegment4 != null)) { num6 = 0; num7 = length; } else { num6 = num3 + subsegment2.Literal.Length; num7 = length - num6; } string str = requestPathSegment.Substring(num6, num7); if (string.IsNullOrEmpty(str)) { return(false); } matchedValues.Add(subsegment.ParameterName, str); subsegment = null; subsegment2 = null; } length = num3; num2--; } if (length != 0) { return(routeSegment.Subsegments[0] is PathParameterSubsegment); } return(true); }