2

Is there a class in the .NET framework which, if given a sequence/enumerable of key value pairs (or anything else I am not rigid on the format of this) can create a query string like this:

?foo=bar&gar=har&print=1

I could do this trivial task myself but I thought I'd ask to save myself from re-inventing the wheel. Why do all those string gymnastics when a single line of code can do it?

Water Cooler v2
  • 32,724
  • 54
  • 166
  • 336

4 Answers4

6

You can use System.Web.HttpUtility.ParseQueryString to create an empty System.Web.HttpValueCollection, and use it like a NameValueCollection.

Example:

var query = System.Web.HttpUtility.ParseQueryString(string.Empty);
query ["foo"] = "bar";
query ["gar"] = "har";
query ["print"] = "1";
var queryString = query.ToString(); // queryString is 'foo=bar&gar=har&print=1'
sloth
  • 99,095
  • 21
  • 171
  • 219
  • 1
    Related: https://connect.microsoft.com/VisualStudio/feedback/details/356144/make-the-httpvaluecollection-class-public-and-move-it-to-system-dll – sloth Oct 29 '13 at 09:46
  • Nice. Thanks for sharing. :-) I guess it'd also be a big decision moving something that's a part of the public API. That reminds me of an attribute that sort of tells the CLR that this entry point is important and will never change as it is a part of the publicly released API. I forget that attribute name. – Water Cooler v2 Oct 29 '13 at 09:57
1

There's nothing built in to the .NET framework, as far as I know, though there are a lot of almosts.

System.Web.HttpRequest.QueryString is a pre-parsed NameValueCollection, not something that can output a querystring. System.NetHttpWebRequest expects you to pass a pre-formed URI, and System.UriBuilder has a Query property, but again, expects a pre-formed string for the entire query string.

However, running a quick search for "querystringbuilder" shows a couple of implementations for this out in the web that could serve. One such is this one by Brad Vincent, which gives you a simple fluent interface:

//take an existing string and replace the 'id' value if it exists (which it does)
//output : "?id=5678&user=tony"
strQuery = new QueryString("id=1234&user=tony").Add("id", "5678", true).ToString();
Avner Shahar-Kashtan
  • 14,492
  • 3
  • 37
  • 63
0

And, though not exactly very elegant, I found a method in RestSharp, as suggested by @sasfrog in the comment to my question. Here's the method.

From RestSharp-master\RestSharp\Http.cs

private string EncodeParameters()
{
  var querystring = new StringBuilder();
  foreach (var p in Parameters)
  {
    if (querystring.Length > 0)
      querystring.Append("&");

    querystring.AppendFormat("{0}={1}", p.Name.UrlEncode(), p.Value.UrlEncode());
  }

  return querystring.ToString();
}

And again, not very elegant and not really what I would have been expecting, but hey, it gets the job done and saves me some typing.

I was really looking for something like Xi Huan's answer (marked the correct answer) but this works as well.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
Water Cooler v2
  • 32,724
  • 54
  • 166
  • 336
0

There's nothing built into the .NET Framework that preserves the order of the query parameters, AFAIK. The following helper does that, skips null values, and converts values to invariant strings. When combined with a KeyValueList, it makes building URIs pretty easy.

public static string ToUrlQuery(IEnumerable<KeyValuePair<string, object>> pairs)
{
    var q = new StringBuilder();
    foreach (var pair in pairs)
        if (pair.Value != null) {
            if (q.Length > 0) q.Append('&');
            q.Append(pair.Key).Append('=').Append(WebUtility.UrlEncode(Convert.ToString(pair.Value, CultureInfo.InvariantCulture)));
        }
    return q.ToString();
}
Edward Brey
  • 40,302
  • 20
  • 199
  • 253