Skip to content

Commit 9249a95

Browse files
Improve support to the dictionary returned by ParseQuery (#20133)
1 parent 10a99c0 commit 9249a95

File tree

6 files changed

+95
-6
lines changed

6 files changed

+95
-6
lines changed

src/Http/Http.Extensions/ref/Microsoft.AspNetCore.Http.Extensions.netcoreapp.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public static partial class HttpRequestMultipartExtensions
4343
public partial class QueryBuilder : System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>>, System.Collections.IEnumerable
4444
{
4545
public QueryBuilder() { }
46+
public QueryBuilder(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues>> parameters) { }
4647
public QueryBuilder(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> parameters) { }
4748
public void Add(string key, System.Collections.Generic.IEnumerable<string> values) { }
4849
public void Add(string key, string value) { }

src/Http/Http.Extensions/src/QueryBuilder.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
using System.Collections;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Text;
78
using System.Text.Encodings.Web;
9+
using Microsoft.Extensions.Primitives;
810

911
namespace Microsoft.AspNetCore.Http.Extensions
1012
{
@@ -23,6 +25,12 @@ public QueryBuilder(IEnumerable<KeyValuePair<string, string>> parameters)
2325
_params = new List<KeyValuePair<string, string>>(parameters);
2426
}
2527

28+
public QueryBuilder(IEnumerable<KeyValuePair<string, StringValues>> parameters)
29+
: this(parameters.SelectMany(kvp => kvp.Value, (kvp, v) => KeyValuePair.Create(kvp.Key, v)))
30+
{
31+
32+
}
33+
2634
public void Add(string key, IEnumerable<string> values)
2735
{
2836
foreach (var value in values)
@@ -78,4 +86,4 @@ IEnumerator IEnumerable.GetEnumerator()
7886
return _params.GetEnumerator();
7987
}
8088
}
81-
}
89+
}

src/Http/Http.Extensions/test/QueryBuilderTests.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using Microsoft.Extensions.Primitives;
67
using Xunit;
78

89
namespace Microsoft.AspNetCore.Http.Extensions
@@ -70,6 +71,18 @@ public void AddMultipleValuesViaConstructor_AddedInOrder()
7071
Assert.Equal("?key1=value1&key2=value2&key3=value3", builder.ToString());
7172
}
7273

74+
[Fact]
75+
public void AddMultipleValuesViaConstructor_WithStringValues()
76+
{
77+
var builder = new QueryBuilder(new[]
78+
{
79+
new KeyValuePair<string, StringValues>("key1", new StringValues(new [] { "value1", string.Empty, "value3" })),
80+
new KeyValuePair<string, StringValues>("key2", string.Empty),
81+
new KeyValuePair<string, StringValues>("key3", StringValues.Empty)
82+
});
83+
Assert.Equal("?key1=value1&key1=&key1=value3&key2=", builder.ToString());
84+
}
85+
7386
[Fact]
7487
public void AddMultipleValuesViaInitializer_AddedInOrder()
7588
{
@@ -95,4 +108,4 @@ public void CopyViaConstructor_AddedInOrder()
95108
Assert.Equal("?key1=value1&key2=value2&key3=value3", builder1.ToString());
96109
}
97110
}
98-
}
111+
}

src/Http/WebUtilities/ref/Microsoft.AspNetCore.WebUtilities.netcoreapp.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ public static partial class MultipartSectionStreamExtensions
216216
public static partial class QueryHelpers
217217
{
218218
public static string AddQueryString(string uri, System.Collections.Generic.IDictionary<string, string> queryString) { throw null; }
219+
public static string AddQueryString(string uri, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues>> queryString) { throw null; }
220+
public static string AddQueryString(string uri, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> queryString) { throw null; }
219221
public static string AddQueryString(string uri, string name, string value) { throw null; }
220222
public static System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues> ParseNullableQuery(string queryString) { throw null; }
221223
public static System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues> ParseQuery(string queryString) { throw null; }

src/Http/WebUtilities/src/QueryHelpers.cs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Text;
78
using System.Text.Encodings.Web;
89
using Microsoft.Extensions.Primitives;
@@ -46,10 +47,10 @@ public static string AddQueryString(string uri, string name, string value)
4647
}
4748

4849
/// <summary>
49-
/// Append the given query keys and values to the uri.
50+
/// Append the given query keys and values to the URI.
5051
/// </summary>
51-
/// <param name="uri">The base uri.</param>
52-
/// <param name="queryString">A collection of name value query pairs to append.</param>
52+
/// <param name="uri">The base URI.</param>
53+
/// <param name="queryString">A dictionary of query keys and values to append.</param>
5354
/// <returns>The combined result.</returns>
5455
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <c>null</c>.</exception>
5556
/// <exception cref="ArgumentNullException"><paramref name="queryString"/> is <c>null</c>.</exception>
@@ -68,7 +69,38 @@ public static string AddQueryString(string uri, IDictionary<string, string> quer
6869
return AddQueryString(uri, (IEnumerable<KeyValuePair<string, string>>)queryString);
6970
}
7071

71-
private static string AddQueryString(
72+
/// <summary>
73+
/// Append the given query keys and values to the URI.
74+
/// </summary>
75+
/// <param name="uri">The base URI.</param>
76+
/// <param name="queryString">A collection of query names and values to append.</param>
77+
/// <returns>The combined result.</returns>
78+
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <c>null</c>.</exception>
79+
/// <exception cref="ArgumentNullException"><paramref name="queryString"/> is <c>null</c>.</exception>
80+
public static string AddQueryString(string uri, IEnumerable<KeyValuePair<string, StringValues>> queryString)
81+
{
82+
if (uri == null)
83+
{
84+
throw new ArgumentNullException(nameof(uri));
85+
}
86+
87+
if (queryString == null)
88+
{
89+
throw new ArgumentNullException(nameof(queryString));
90+
}
91+
92+
return AddQueryString(uri, queryString.SelectMany(kvp => kvp.Value, (kvp, v) => KeyValuePair.Create(kvp.Key, v)));
93+
}
94+
95+
/// <summary>
96+
/// Append the given query keys and values to the URI.
97+
/// </summary>
98+
/// <param name="uri">The base URI.</param>
99+
/// <param name="queryString">A collection of name value query pairs to append.</param>
100+
/// <returns>The combined result.</returns>
101+
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <c>null</c>.</exception>
102+
/// <exception cref="ArgumentNullException"><paramref name="queryString"/> is <c>null</c>.</exception>
103+
public static string AddQueryString(
72104
string uri,
73105
IEnumerable<KeyValuePair<string, string>> queryString)
74106
{

src/Http/WebUtilities/test/QueryHelpersTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using Microsoft.Extensions.Primitives;
78
using Xunit;
89

910
namespace Microsoft.AspNetCore.WebUtilities
@@ -119,5 +120,37 @@ public void AddQueryStringWithDictionary(string uri, string expectedUri)
119120
var result = QueryHelpers.AddQueryString(uri, queryStrings);
120121
Assert.Equal(expectedUri, result);
121122
}
123+
124+
[Theory]
125+
[InlineData("http://contoso.com/", "http://contoso.com/?param1=value1&param1=&param1=value3&param2=")]
126+
[InlineData("http://contoso.com/someaction", "http://contoso.com/someaction?param1=value1&param1=&param1=value3&param2=")]
127+
[InlineData("http://contoso.com/someaction?param2=1", "http://contoso.com/someaction?param2=1&param1=value1&param1=&param1=value3&param2=")]
128+
[InlineData("http://contoso.com/some#action", "http://contoso.com/some?param1=value1&param1=&param1=value3&param2=#action")]
129+
[InlineData("http://contoso.com/some?param2=1#action", "http://contoso.com/some?param2=1&param1=value1&param1=&param1=value3&param2=#action")]
130+
[InlineData("http://contoso.com/#action", "http://contoso.com/?param1=value1&param1=&param1=value3&param2=#action")]
131+
[InlineData(
132+
"http://contoso.com/someaction?q=test#anchor?value",
133+
"http://contoso.com/someaction?q=test&param1=value1&param1=&param1=value3&param2=#anchor?value")]
134+
[InlineData(
135+
"http://contoso.com/someaction#anchor?stuff",
136+
"http://contoso.com/someaction?param1=value1&param1=&param1=value3&param2=#anchor?stuff")]
137+
[InlineData(
138+
"http://contoso.com/someaction?name?something",
139+
"http://contoso.com/someaction?name?something&param1=value1&param1=&param1=value3&param2=")]
140+
[InlineData(
141+
"http://contoso.com/someaction#name#something",
142+
"http://contoso.com/someaction?param1=value1&param1=&param1=value3&param2=#name#something")]
143+
public void AddQueryStringWithEnumerableOfKeysAndStringValues(string uri, string expectedUri)
144+
{
145+
var queryStrings = new Dictionary<string, StringValues>()
146+
{
147+
{ "param1", new StringValues(new [] { "value1", string.Empty, "value3" }) },
148+
{ "param2", string.Empty },
149+
{ "param3", StringValues.Empty }
150+
};
151+
152+
var result = QueryHelpers.AddQueryString(uri, queryStrings);
153+
Assert.Equal(expectedUri, result);
154+
}
122155
}
123156
}

0 commit comments

Comments
 (0)