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, 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 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(); } // 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(); }