/// <summary>Adds a parameter value.</summary> /// <param name="type">Type of the parameter (must be 'Path' or 'Query').</param> /// <param name="name">Parameter name.</param> /// <param name="value">Parameter value.</param> public void AddParameter(RequestParameterType type, string name, string value) { name.ThrowIfNull("name"); if (value == null) { Logger.Warning("Add parameter should not get null values. type={0}, name={1}", type, name); return; } switch (type) { case RequestParameterType.Path: if (!PathParameters.ContainsKey(name)) { PathParameters[name] = new List <string> { value }; } else { PathParameters[name].Add(value); } break; case RequestParameterType.Query: QueryParameters.Add(new KeyValuePair <string, string>(name, value)); break; default: throw new ArgumentOutOfRangeException("type"); } }
/// <summary> /// Builds the REST path string builder based on <see cref="PathParameters"/> and the URI template spec /// http://tools.ietf.org/html/rfc6570. /// </summary> /// <returns></returns> private StringBuilder BuildRestPath() { if (string.IsNullOrEmpty(Path)) { return(new StringBuilder(string.Empty)); } var restPath = new StringBuilder(Path); var matches = PathParametersPattern.Matches(restPath.ToString()); foreach (var match in matches) { var matchStr = match.ToString(); // Strip the first and last characters: '{' and '}'. var content = matchStr.Substring(1, matchStr.Length - 2); var op = string.Empty; // If the content's first character is an operator, save and remove it from the content string. if (OPERATORS.Contains(content[0].ToString())) { op = content[0].ToString(); content = content.Substring(1); } var newContent = new StringBuilder(); // Iterate over all possible parameters. var parameters = content.Split(','); for (var index = 0; index < parameters.Length; ++index) { var parameter = parameters[index]; var parameterName = parameter; var containStar = false; var numOfChars = 0; // Check if it ends with '*'. if (parameterName[parameterName.Length - 1] == '*') { containStar = true; parameterName = parameterName.Substring(0, parameterName.Length - 1); } // Check if it contains :n which means we should only use the first n characters of this parameter. if (parameterName.Contains(":")) { if (!int.TryParse(parameterName.Substring(parameterName.IndexOf(":") + 1), out numOfChars)) { throw new ArgumentException( string.Format("Can't parse number after ':' in Path \"{0}\". Parameter is \"{1}\"", Path, parameterName), Path); } parameterName = parameterName.Substring(0, parameterName.IndexOf(":")); } // We can improve the following if statement, but for readability we will leave it like that. var joiner = op; var start = op; switch (op) { case "+": start = index == 0 ? "" : ","; joiner = ","; break; case ".": if (!containStar) { joiner = ","; } break; case "/": if (!containStar) { joiner = ","; } break; case "#": start = index == 0 ? "#" : ","; joiner = ","; break; case "?": start = (index == 0 ? "?" : "&") + parameterName + "="; joiner = ","; if (containStar) { joiner = "&" + parameterName + "="; } break; case "&": case ";": start = op + parameterName + "="; joiner = ","; if (containStar) { joiner = op + parameterName + "="; } break; // No operator, in that case just ','. default: if (index > 0) { start = ","; } joiner = ","; break; } // Check if a path parameter equals the name which appears in the REST path. if (PathParameters.ContainsKey(parameterName)) { var value = string.Join(joiner, PathParameters[parameterName]); // Check if we need to use a substring of the value. if (numOfChars != 0 && numOfChars < value.Length) { value = value.Substring(0, numOfChars); } if (op != "+" && op != "#" && PathParameters[parameterName].Count == 1) { value = Uri.EscapeDataString(value); } value = start + value; newContent.Append(value); } else { throw new ArgumentException( string.Format("Path \"{0}\" misses a \"{1}\" parameter", Path, parameterName), Path); } } if (op == ";") { if (newContent[newContent.Length - 1] == '=') { newContent = newContent.Remove(newContent.Length - 1, 1); } newContent = newContent.Replace("=;", ";"); } restPath = restPath.Replace(matchStr, newContent.ToString()); } return(restPath); }