// Step 2: If the route is a match generate the appropriate URI public string BindValues(IDictionary <string, object> acceptedValues) { var context = new UriBuildingContext(); for (var i = 0; i < _template.Segments.Count; i++) { Debug.Assert(context.BufferState == SegmentState.Beginning); Debug.Assert(context.UriState == SegmentState.Beginning); var segment = _template.Segments[i]; for (var j = 0; j < segment.Parts.Count; j++) { var part = segment.Parts[j]; if (part.IsLiteral) { if (!context.Accept(part.Text)) { return(null); } } else if (part.IsParameter) { // If it's a parameter, get its value object value; var hasValue = acceptedValues.TryGetValue(part.Name, out value); if (hasValue) { acceptedValues.Remove(part.Name); } var isSameAsDefault = false; object defaultValue; if (_defaults != null && _defaults.TryGetValue(part.Name, out defaultValue)) { if (RoutePartsEqual(value, defaultValue)) { isSameAsDefault = true; } } var converted = Convert.ToString(value, CultureInfo.InvariantCulture); if (isSameAsDefault) { // If the accepted value is the same as the default value buffer it since // we won't necessarily add it to the URI we generate. if (!context.Buffer(converted)) { return(null); } } else { // If the value is not accepted, it is null or empty value in the // middle of the segment. We accept this if the parameter is an // optional parameter and it is preceded by an optional seperator. // I this case, we need to remove the optional seperator that we // have added to the URI // Example: template = {id}.{format?}. parameters: id=5 // In this case after we have generated "5.", we wont find any value // for format, so we remove '.' and generate 5. if (!context.Accept(converted)) { if (j != 0 && part.IsOptional && segment.Parts[j - 1].IsOptionalSeperator) { context.Remove(segment.Parts[j - 1].Text); } else { return(null); } } } } } context.EndSegment(); } // Encode the URI before we append the query string, otherwise we would double encode the query string var encoded = new StringBuilder(); encoded.Append(UriEncode(context.Build())); // Generate the query string from the remaining values var queryBuilder = new QueryBuilder(); foreach (var kvp in acceptedValues) { if (_defaults != null && _defaults.ContainsKey(kvp.Key)) { // This value is a 'filter' we don't need to put it in the query string. continue; } var converted = Convert.ToString(kvp.Value, CultureInfo.InvariantCulture); if (String.IsNullOrEmpty(converted)) { continue; } queryBuilder.Add(kvp.Key, converted); } encoded.Append(queryBuilder.ToString()); return(encoded.ToString()); }
private string BindValues(UriBuildingContext context, RouteValueDictionary acceptedValues) { for (var i = 0; i < _template.Segments.Count; i++) { Debug.Assert(context.BufferState == SegmentState.Beginning); Debug.Assert(context.UriState == SegmentState.Beginning); var segment = _template.Segments[i]; for (var j = 0; j < segment.Parts.Count; j++) { var part = segment.Parts[j]; if (part.IsLiteral) { if (!context.Accept(part.Text)) { return(null); } } else if (part.IsParameter) { // If it's a parameter, get its value var hasValue = acceptedValues.TryGetValue(part.Name, out var value); if (hasValue) { acceptedValues.Remove(part.Name); } var isSameAsDefault = false; if (_defaults != null && _defaults.TryGetValue(part.Name, out var defaultValue) && RoutePartsEqual(value, defaultValue)) { isSameAsDefault = true; } var converted = Convert.ToString(value, CultureInfo.InvariantCulture); if (isSameAsDefault) { // If the accepted value is the same as the default value buffer it since // we won't necessarily add it to the URI we generate. if (!context.Buffer(converted)) { return(null); } } else { // If the value is not accepted, it is null or empty value in the // middle of the segment. We accept this if the parameter is an // optional parameter and it is preceded by an optional seperator. // I this case, we need to remove the optional seperator that we // have added to the URI // Example: template = {id}.{format?}. parameters: id=5 // In this case after we have generated "5.", we wont find any value // for format, so we remove '.' and generate 5. if (!context.Accept(converted)) { if (j != 0 && part.IsOptional && segment.Parts[j - 1].IsOptionalSeperator) { context.Remove(segment.Parts[j - 1].Text); } else { return(null); } } } } } context.EndSegment(); } // Generate the query string from the remaining values var wroteFirst = false; foreach (var kvp in acceptedValues) { if (_defaults != null && _defaults.ContainsKey(kvp.Key)) { // This value is a 'filter' we don't need to put it in the query string. continue; } var values = kvp.Value as IEnumerable; if (values != null && !(values is string)) { foreach (var value in values) { wroteFirst |= AddParameterToContext(context, kvp.Key, value, wroteFirst); } } else { wroteFirst |= AddParameterToContext(context, kvp.Key, kvp.Value, wroteFirst); } } return(context.ToString()); }
// Step 2: If the route is a match generate the appropriate URI public string BindValues(IDictionary<string, object> acceptedValues) { var context = new UriBuildingContext(); for (var i = 0; i < _template.Segments.Count; i++) { Debug.Assert(context.BufferState == SegmentState.Beginning); Debug.Assert(context.UriState == SegmentState.Beginning); var segment = _template.Segments[i]; for (var j = 0; j < segment.Parts.Count; j++) { var part = segment.Parts[j]; if (part.IsLiteral) { if (!context.Accept(part.Text)) { return null; } } else if (part.IsParameter) { // If it's a parameter, get its value object value; var hasValue = acceptedValues.TryGetValue(part.Name, out value); if (hasValue) { acceptedValues.Remove(part.Name); } var isSameAsDefault = false; object defaultValue; if (_defaults != null && _defaults.TryGetValue(part.Name, out defaultValue)) { if (RoutePartsEqual(value, defaultValue)) { isSameAsDefault = true; } } var converted = Convert.ToString(value, CultureInfo.InvariantCulture); if (isSameAsDefault) { // If the accepted value is the same as the default value buffer it since // we won't necessarily add it to the URI we generate. if (!context.Buffer(converted)) { return null; } } else { // If the value is not accepted, it is null or empty value in the // middle of the segment. We accept this if the parameter is an // optional parameter and it is preceded by an optional seperator. // I this case, we need to remove the optional seperator that we // have added to the URI // Example: template = {id}.{format?}. parameters: id=5 // In this case after we have generated "5.", we wont find any value // for format, so we remove '.' and generate 5. if (!context.Accept(converted)) { if (j != 0 && part.IsOptional && segment.Parts[j - 1].IsOptionalSeperator) { context.Remove(segment.Parts[j - 1].Text); } else { return null; } } } } } context.EndSegment(); } // Encode the URI before we append the query string, otherwise we would double encode the query string var encoded = new StringBuilder(); encoded.Append(UriEncode(context.Build())); // Generate the query string from the remaining values var queryBuilder = new QueryBuilder(); foreach (var kvp in acceptedValues) { if (_defaults != null && _defaults.ContainsKey(kvp.Key)) { // This value is a 'filter' we don't need to put it in the query string. continue; } var converted = Convert.ToString(kvp.Value, CultureInfo.InvariantCulture); if (String.IsNullOrEmpty(converted)) { continue; } queryBuilder.Add(kvp.Key, converted); } encoded.Append(queryBuilder.ToString()); return encoded.ToString(); }