aspnet/HttpAbstractions

QueryString.Create(...) excludes key when StringValues is empty

austindrenski opened this issue · 2 comments

QueryString.Create(IEnumerable<KeyValuePair<string, StringValues>> parameters) doesn't append a key unless it has associated values.

This was unexpected because it means that parsing an incoming query string into an IEnumerable<KeyValuePair<string, StringValues>> and then immediately reconstructing a QueryString results in information loss.

We ran across this after some new middleware attempted to validate parameter values (by treating all query string entries as KeyValuePair<string, StringValues>) and unexpectedly removed a key meant to be read as a switch/flag/indicator in the event no values are supplied.

Is this behavior intentional or defined by a standard?

/// <summary>
/// Creates a query string composed from the given name value pairs.
/// </summary>
/// <param name="parameters"></param>
/// <returns>The resulting QueryString</returns>
public static QueryString Create(IEnumerable<KeyValuePair<string, StringValues>> parameters)
{
var builder = new StringBuilder();
bool first = true;
foreach (var pair in parameters)
{
foreach (var value in pair.Value)
{
builder.Append(first ? "?" : "&");
first = false;
builder.Append(UrlEncoder.Default.Encode(pair.Key));
builder.Append("=");
builder.Append(UrlEncoder.Default.Encode(value));
}
}
return new QueryString(builder.ToString());
}

By the RFC 3986, QueryStrings don't need to have key=value data. So it does seem like a bug, however it is odd that you are using a special flag in the query string. Maybe as a work around, you can just check if the QueryString is empty rather than relying on a special value?

This issue was moved to dotnet/aspnetcore#2679