private bool AddParameterToContext(UriBuildingContext context, string key, object value, bool wroteFirst) { var converted = Convert.ToString(value, CultureInfo.InvariantCulture); if (!string.IsNullOrEmpty(converted)) { context.Writer.Write(wroteFirst ? '&' : '?'); _urlEncoder.Encode(context.Writer, key); context.Writer.Write('='); _urlEncoder.Encode(context.Writer, converted); return(true); } return(false); }
private string BindValues(UriBuildingContext context, DispatcherValueCollection acceptedValues) { for (var i = 0; i < _pattern.PathSegments.Count; i++) { Debug.Assert(context.BufferState == SegmentState.Beginning); Debug.Assert(context.UriState == SegmentState.Beginning); var segment = _pattern.PathSegments[i]; for (var j = 0; j < segment.Parts.Count; j++) { var part = segment.Parts[j]; if (part.IsLiteral) { if (!context.Accept(_urlEncoder, ((RoutePatternLiteral)part).Content)) { return(null); } } else if (part.IsSeparator) { if (!context.Accept(_urlEncoder, ((RoutePatternSeparator)part).Content)) { return(null); } } else if (part.IsParameter && part is RoutePatternParameter parameter) { // If it's a parameter, get its value object value; var hasValue = acceptedValues.TryGetValue(parameter.Name, out value); if (hasValue) { acceptedValues.Remove(parameter.Name); } var isSameAsDefault = false; object defaultValue; if (_defaults != null && _defaults.TryGetValue(parameter.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(_urlEncoder, 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(_urlEncoder, converted)) { if (j != 0 && parameter.IsOptional && segment.Parts[j - 1].IsSeparator) { context.Remove(((RoutePatternSeparator)segment.Parts[j - 1]).Content); } 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()); }