Fixes QueryHelpers.AddQueryString() throws when one of the dictionary values is null #16647 (#17177)

This commit is contained in:
André Silva 2019-11-18 21:03:44 -03:00 committed by Chris Ross
parent f1123af4c1
commit 8d1c8005d8
2 changed files with 35 additions and 14 deletions

View File

@ -9,6 +9,9 @@ using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.WebUtilities
{
/// <summary>
/// Provides methods for parsing and manipulating query strings.
/// </summary>
public static class QueryHelpers
{
/// <summary>
@ -18,6 +21,9 @@ namespace Microsoft.AspNetCore.WebUtilities
/// <param name="name">The name of the query key.</param>
/// <param name="value">The query value.</param>
/// <returns>The combined result.</returns>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
public static string AddQueryString(string uri, string name, string value)
{
if (uri == null)
@ -45,6 +51,8 @@ namespace Microsoft.AspNetCore.WebUtilities
/// <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, IDictionary<string, string> 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;
}
/// <summary>
/// Parse a query string into its component key and value parts.
/// </summary>
@ -188,4 +200,4 @@ namespace Microsoft.AspNetCore.WebUtilities
return accumulator.GetResults();
}
}
}
}

View File

@ -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<ArgumentNullException>("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<string, string>()
{
{ "hello", "world" },
{ "some", "text" }
{ "some", "text" },
{ "another", string.Empty },
{ "invisible", null }
};
var result = QueryHelpers.AddQueryString(uri, queryStrings);
Assert.Equal(expectedUri, result);
}
}
}
}