diff --git a/src/Http/WebUtilities/src/QueryHelpers.cs b/src/Http/WebUtilities/src/QueryHelpers.cs index c1c23b64e9..a3b13b033c 100644 --- a/src/Http/WebUtilities/src/QueryHelpers.cs +++ b/src/Http/WebUtilities/src/QueryHelpers.cs @@ -9,6 +9,9 @@ using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.WebUtilities { + /// + /// Provides methods for parsing and manipulating query strings. + /// public static class QueryHelpers { /// @@ -18,6 +21,9 @@ namespace Microsoft.AspNetCore.WebUtilities /// The name of the query key. /// The query value. /// The combined result. + /// is null. + /// is null. + /// is null. public static string AddQueryString(string uri, string name, string value) { if (uri == null) @@ -45,6 +51,8 @@ namespace Microsoft.AspNetCore.WebUtilities /// The base uri. /// A collection of name value query pairs to append. /// The combined result. + /// is null. + /// is null. public static string AddQueryString(string uri, IDictionary queryString) { if (uri == null) @@ -91,6 +99,11 @@ namespace Microsoft.AspNetCore.WebUtilities sb.Append(uriToBeAppended); foreach (var parameter in queryString) { + if (parameter.Value == null) + { + continue; + } + sb.Append(hasQuery ? '&' : '?'); sb.Append(UrlEncoder.Default.Encode(parameter.Key)); sb.Append('='); @@ -119,7 +132,6 @@ namespace Microsoft.AspNetCore.WebUtilities return result; } - /// /// Parse a query string into its component key and value parts. /// @@ -188,4 +200,4 @@ namespace Microsoft.AspNetCore.WebUtilities return accumulator.GetResults(); } } -} \ No newline at end of file +} diff --git a/src/Http/WebUtilities/test/QueryHelpersTests.cs b/src/Http/WebUtilities/test/QueryHelpersTests.cs index 5607ab87aa..a64bcbf03b 100644 --- a/src/Http/WebUtilities/test/QueryHelpersTests.cs +++ b/src/Http/WebUtilities/test/QueryHelpersTests.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; using Xunit; @@ -53,6 +54,12 @@ namespace Microsoft.AspNetCore.WebUtilities Assert.Equal(new[] { "value1", "" }, collection[""]); } + [Fact] + public void AddQueryStringWithNullValueThrows() + { + Assert.Throws("value" ,() => QueryHelpers.AddQueryString("http://contoso.com/", "hello", null)); + } + [Theory] [InlineData("http://contoso.com/", "http://contoso.com/?hello=world")] [InlineData("http://contoso.com/someaction", "http://contoso.com/someaction?hello=world")] @@ -81,34 +88,36 @@ namespace Microsoft.AspNetCore.WebUtilities } [Theory] - [InlineData("http://contoso.com/", "http://contoso.com/?hello=world&some=text")] - [InlineData("http://contoso.com/someaction", "http://contoso.com/someaction?hello=world&some=text")] - [InlineData("http://contoso.com/someaction?q=1", "http://contoso.com/someaction?q=1&hello=world&some=text")] - [InlineData("http://contoso.com/some#action", "http://contoso.com/some?hello=world&some=text#action")] - [InlineData("http://contoso.com/some?q=1#action", "http://contoso.com/some?q=1&hello=world&some=text#action")] - [InlineData("http://contoso.com/#action", "http://contoso.com/?hello=world&some=text#action")] + [InlineData("http://contoso.com/", "http://contoso.com/?hello=world&some=text&another=")] + [InlineData("http://contoso.com/someaction", "http://contoso.com/someaction?hello=world&some=text&another=")] + [InlineData("http://contoso.com/someaction?q=1", "http://contoso.com/someaction?q=1&hello=world&some=text&another=")] + [InlineData("http://contoso.com/some#action", "http://contoso.com/some?hello=world&some=text&another=#action")] + [InlineData("http://contoso.com/some?q=1#action", "http://contoso.com/some?q=1&hello=world&some=text&another=#action")] + [InlineData("http://contoso.com/#action", "http://contoso.com/?hello=world&some=text&another=#action")] [InlineData( "http://contoso.com/someaction?q=test#anchor?value", - "http://contoso.com/someaction?q=test&hello=world&some=text#anchor?value")] + "http://contoso.com/someaction?q=test&hello=world&some=text&another=#anchor?value")] [InlineData( "http://contoso.com/someaction#anchor?stuff", - "http://contoso.com/someaction?hello=world&some=text#anchor?stuff")] + "http://contoso.com/someaction?hello=world&some=text&another=#anchor?stuff")] [InlineData( "http://contoso.com/someaction?name?something", - "http://contoso.com/someaction?name?something&hello=world&some=text")] + "http://contoso.com/someaction?name?something&hello=world&some=text&another=")] [InlineData( "http://contoso.com/someaction#name#something", - "http://contoso.com/someaction?hello=world&some=text#name#something")] + "http://contoso.com/someaction?hello=world&some=text&another=#name#something")] public void AddQueryStringWithDictionary(string uri, string expectedUri) { var queryStrings = new Dictionary() { { "hello", "world" }, - { "some", "text" } + { "some", "text" }, + { "another", string.Empty }, + { "invisible", null } }; var result = QueryHelpers.AddQueryString(uri, queryStrings); Assert.Equal(expectedUri, result); } } -} \ No newline at end of file +}