public string BuildLocalisedPath(RouteValues values, string regionCode, CultureInfo cultureCode) { if (this.parsedLocalisedRoute == null) { throw new InvalidOperationException($"This route `{this.Path}` is not localisable"); } var routeValues = new RouteValues(values); routeValues["regionCode"] = regionCode; routeValues["cultureCode"] = cultureCode.Name; return(this.parsedLocalisedRoute.BuildPath(routeValues)); }
/// <summary> /// /// </summary> /// <param name="userValues"></param> /// <returns></returns> public string BuildPath(RouteValues userValues) { userValues = userValues ?? new RouteValues(); if (this.parameterNames.Any(de => !userValues.ContainsKey(de.Key))) { log.Error("User route values did not contain a necessary parameter to build path. Url: {url}, User values: {userValues}", this.Url, userValues.Keys); return(null); } var urlBuilder = new StringBuilder(); int tokensCount = this.tokens.Length - 1; for (int i = tokensCount; i >= 0; i--) { PatternToken token = this.tokens[i]; if (token == null) { if (i < tokensCount && urlBuilder.Length > 0 && urlBuilder[0] != '/') { urlBuilder.Insert(0, '/'); } continue; } if (token.Type == PatternTokenType.Literal) { urlBuilder.Insert(0, token.Name); continue; } var tokenValue = userValues[token.Name]; if (tokenValue != null) { urlBuilder.Insert(0, tokenValue.ToString()); } } urlBuilder.Insert(0, '/'); return(urlBuilder.ToString()); }
public virtual RouteValues GetRouteValues(Url url, HttpMethod method, RequestType requestType) { if (this.HandledMethods != 0 && (this.HandledMethods & method) != method) { return(null); } if (this.RequestTypes != 0 && this.RequestTypes != requestType) { return(null); } RouteValues routeValues = null; // Check localised route first, otherwise localised wildcard and other routes of the form "/{param}" can accidentally match if (this.Localised) { routeValues = this.parsedLocalisedRoute.Match(url.Path); // Simple check to prevent most route collisions with /{regionCode}/{cultureCode} // If the regionCode isnt 2 chars, we almost certainly shouldn't be routed here var regionCode = (string)routeValues?["regionCode"]; if (regionCode != null && regionCode.Length != 2) { return(null); } } if (routeValues == null) { routeValues = this.parsedRoute.Match(url.Path); } if (routeValues != null) { routeValues["AreaName"] = this.areaName; } return(routeValues); }
public RouteData(IRoute route, RouteValues values) { this.Route = route; this.Values = values; }
public RouteValues Match(string path) { var ret = new RouteValues(); string url = this.Url; string[] argSegs; int argsCount; if (String.IsNullOrEmpty(path)) { argSegs = null; argsCount = 0; } else { // TODO: cache indexof if (string.Compare(url, path, StringComparison.Ordinal) == 0 && url.IndexOf('{') < 0) { return(new RouteValues()); } argSegs = path.TrimLeading('/').Split('/'); argsCount = argSegs.Length; } if (argsCount == 1 && String.IsNullOrEmpty(argSegs[0])) { argsCount = 0; } if ((this.hasCatchAllSegment && argsCount < this.segmentCount) || (!this.hasCatchAllSegment && argsCount != this.segmentCount)) { return(null); } int i = 0; foreach (PatternSegment segment in this.segments) { if (i >= argsCount) { break; } if (segment.AllTokensAreLiteral) { if (String.Compare(argSegs[i], segment.Tokens[0].Name, StringComparison.OrdinalIgnoreCase) != 0) { return(null); } i++; continue; } string pathSegment = argSegs[i]; int pathSegmentLength = pathSegment != null ? pathSegment.Length : -1; int pathIndex = 0; PatternTokenType tokenType; List <PatternToken> tokens = segment.Tokens; int tokensCount = tokens.Count; // Process the path segments ignoring the defaults for (int tokenIndex = 0; tokenIndex < tokensCount; tokenIndex++) { var token = tokens[tokenIndex]; if (pathIndex > pathSegmentLength - 1) { return(null); } tokenType = token.Type; var tokenName = token.Name; // Catch-all if (i > this.segmentCount - 1 || tokenType == PatternTokenType.CatchAll) { if (tokenType != PatternTokenType.CatchAll) { return(null); } StringBuilder sb = new StringBuilder(); for (int j = i; j < argsCount; j++) { if (j > i) { sb.Append('/'); } sb.Append(argSegs[j]); } ret.Add(tokenName, sb.ToString()); break; } // Literal sections if (token.Type == PatternTokenType.Literal) { int nameLen = tokenName.Length; if (pathSegmentLength < nameLen || String.Compare(pathSegment, pathIndex, tokenName, 0, nameLen, StringComparison.OrdinalIgnoreCase) != 0) { return(null); } pathIndex += nameLen; continue; } int nextTokenIndex = tokenIndex + 1; if (nextTokenIndex >= tokensCount) { // Last token ret.Add(tokenName, pathSegment.Substring(pathIndex)); continue; } // Next token is a literal - greedy matching. It seems .NET // uses a simple and naive algorithm here which finds the // last ocurrence of the next section literal and assigns // everything before that to this token. See the // GetRouteData28 test in RouteTest.cs var nextToken = tokens[nextTokenIndex]; string nextTokenName = nextToken.Name; int lastIndex = pathSegment.LastIndexOf(nextTokenName, pathSegmentLength - 1, pathSegmentLength - pathIndex, StringComparison.OrdinalIgnoreCase); if (lastIndex == -1) { return(null); } int copyLength = lastIndex - pathIndex; string sectionValue = pathSegment.Substring(pathIndex, copyLength); if (String.IsNullOrEmpty(sectionValue)) { return(null); } ret.Add(tokenName, sectionValue); pathIndex += copyLength; } i++; } if (i < this.segmentCount) { return(null); } return(ret); }
public virtual string BuildPath(RouteValues values = null, bool localised = false) { var url = localised ? this.parsedLocalisedRoute.BuildPath(values) : this.parsedRoute.BuildPath(values); return(url); }