Skip to content

Improve support to the dictionary returned by ParseQuery #20133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Mar 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public static partial class HttpRequestMultipartExtensions
public partial class QueryBuilder : System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>>, System.Collections.IEnumerable
{
public QueryBuilder() { }
public QueryBuilder(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues>> parameters) { }
public QueryBuilder(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> parameters) { }
public void Add(string key, System.Collections.Generic.IEnumerable<string> values) { }
public void Add(string key, string value) { }
Expand Down
10 changes: 9 additions & 1 deletion src/Http/Http.Extensions/src/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.Extensions.Primitives;

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

public QueryBuilder(IEnumerable<KeyValuePair<string, StringValues>> parameters)
: this(parameters.SelectMany(kvp => kvp.Value, (kvp, v) => KeyValuePair.Create(kvp.Key, v)))
{

}

public void Add(string key, IEnumerable<string> values)
{
foreach (var value in values)
Expand Down Expand Up @@ -78,4 +86,4 @@ IEnumerator IEnumerable.GetEnumerator()
return _params.GetEnumerator();
}
}
}
}
15 changes: 14 additions & 1 deletion src/Http/Http.Extensions/test/QueryBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using Microsoft.Extensions.Primitives;
using Xunit;

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

[Fact]
public void AddMultipleValuesViaConstructor_WithStringValues()
{
var builder = new QueryBuilder(new[]
{
new KeyValuePair<string, StringValues>("key1", new StringValues(new [] { "value1", string.Empty, "value3" })),
new KeyValuePair<string, StringValues>("key2", string.Empty),
new KeyValuePair<string, StringValues>("key3", StringValues.Empty)
});
Assert.Equal("?key1=value1&key1=&key1=value3&key2=", builder.ToString());
}

[Fact]
public void AddMultipleValuesViaInitializer_AddedInOrder()
{
Expand All @@ -95,4 +108,4 @@ public void CopyViaConstructor_AddedInOrder()
Assert.Equal("?key1=value1&key2=value2&key3=value3", builder1.ToString());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ public static partial class MultipartSectionStreamExtensions
public static partial class QueryHelpers
{
public static string AddQueryString(string uri, System.Collections.Generic.IDictionary<string, string> queryString) { throw null; }
public static string AddQueryString(string uri, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues>> queryString) { throw null; }
public static string AddQueryString(string uri, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> queryString) { throw null; }
public static string AddQueryString(string uri, string name, string value) { throw null; }
public static System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues> ParseNullableQuery(string queryString) { throw null; }
public static System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues> ParseQuery(string queryString) { throw null; }
Expand Down
40 changes: 36 additions & 4 deletions src/Http/WebUtilities/src/QueryHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.Extensions.Primitives;
Expand Down Expand Up @@ -46,10 +47,10 @@ public static string AddQueryString(string uri, string name, string value)
}

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

private static string AddQueryString(
/// <summary>
/// Append the given query keys and values to the URI.
/// </summary>
/// <param name="uri">The base URI.</param>
/// <param name="queryString">A collection of query names and values to append.</param>
/// <returns>The combined result.</returns>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="queryString"/> is <c>null</c>.</exception>
public static string AddQueryString(string uri, IEnumerable<KeyValuePair<string, StringValues>> queryString)
{
if (uri == null)
{
throw new ArgumentNullException(nameof(uri));
}

if (queryString == null)
{
throw new ArgumentNullException(nameof(queryString));
}

return AddQueryString(uri, queryString.SelectMany(kvp => kvp.Value, (kvp, v) => KeyValuePair.Create(kvp.Key, v)));
}

/// <summary>
/// Append the given query keys and values to the URI.
/// </summary>
/// <param name="uri">The base URI.</param>
/// <param name="queryString">A collection of name value query pairs to append.</param>
/// <returns>The combined result.</returns>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="queryString"/> is <c>null</c>.</exception>
public static string AddQueryString(
string uri,
IEnumerable<KeyValuePair<string, string>> queryString)
{
Expand Down
33 changes: 33 additions & 0 deletions src/Http/WebUtilities/test/QueryHelpersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Primitives;
using Xunit;

namespace Microsoft.AspNetCore.WebUtilities
Expand Down Expand Up @@ -119,5 +120,37 @@ public void AddQueryStringWithDictionary(string uri, string expectedUri)
var result = QueryHelpers.AddQueryString(uri, queryStrings);
Assert.Equal(expectedUri, result);
}

[Theory]
[InlineData("http://contoso.com/", "http://contoso.com/?param1=value1&param1=&param1=value3&param2=")]
[InlineData("http://contoso.com/someaction", "http://contoso.com/someaction?param1=value1&param1=&param1=value3&param2=")]
[InlineData("http://contoso.com/someaction?param2=1", "http://contoso.com/someaction?param2=1&param1=value1&param1=&param1=value3&param2=")]
[InlineData("http://contoso.com/some#action", "http://contoso.com/some?param1=value1&param1=&param1=value3&param2=#action")]
[InlineData("http://contoso.com/some?param2=1#action", "http://contoso.com/some?param2=1&param1=value1&param1=&param1=value3&param2=#action")]
[InlineData("http://contoso.com/#action", "http://contoso.com/?param1=value1&param1=&param1=value3&param2=#action")]
[InlineData(
"http://contoso.com/someaction?q=test#anchor?value",
"http://contoso.com/someaction?q=test&param1=value1&param1=&param1=value3&param2=#anchor?value")]
[InlineData(
"http://contoso.com/someaction#anchor?stuff",
"http://contoso.com/someaction?param1=value1&param1=&param1=value3&param2=#anchor?stuff")]
[InlineData(
"http://contoso.com/someaction?name?something",
"http://contoso.com/someaction?name?something&param1=value1&param1=&param1=value3&param2=")]
[InlineData(
"http://contoso.com/someaction#name#something",
"http://contoso.com/someaction?param1=value1&param1=&param1=value3&param2=#name#something")]
public void AddQueryStringWithEnumerableOfKeysAndStringValues(string uri, string expectedUri)
{
var queryStrings = new Dictionary<string, StringValues>()
{
{ "param1", new StringValues(new [] { "value1", string.Empty, "value3" }) },
{ "param2", string.Empty },
{ "param3", StringValues.Empty }
};

var result = QueryHelpers.AddQueryString(uri, queryStrings);
Assert.Equal(expectedUri, result);
}
}
}