19

I want to be able to build URL query strings by just adding the key and value to some helper class and have it return this as a URL query. I know this can be done, like so:

var queryBuilder= HttpUtility.ParseQueryString("http://baseurl.com/?");
queryBuilder.Add("Key", "Value");
string url =  queryBuilder.ToString();

Which is exactly the behaviour I'm after. However, this class exists in the famously large System.Web and I'd rather not bring that whole library in for this. Is there an alternative somewhere?

Caleb Kleveter
  • 11,170
  • 8
  • 62
  • 92
MartinM
  • 1,736
  • 5
  • 20
  • 33
  • Try System.Uri: http://msdn.microsoft.com/pl-pl/library/system.uri%28v=vs.110%29.aspx –  Dec 12 '14 at 11:47
  • 1
    why do you care about the size of System.Web? its anyway already deployed within the framework – fixagon Dec 12 '14 at 11:56
  • here a solution: http://stackoverflow.com/questions/14517798/append-values-to-query-string – lem2802 Dec 12 '14 at 11:57
  • 1
    If you look at the source the code to parse/tostring is pretty simple with no additional dependencies to System.Web; E.g. http://referencesource.microsoft.com/#System.Web/HttpValueCollection.cs,222f9a1bfd1f9a98 – Alex K. Dec 12 '14 at 12:06
  • pwas, I don't think / can't see where the System.Uri class allows for adding a query parameter like the way I have shown. lem2802 the solutions in your link all use HttpUtility..? fix_likes_coding, there are a number of reasons why I - or others - wouldn't want it referenced anyway, such as deploying the code as a package and not wanting extra dependencies. – MartinM Dec 12 '14 at 12:10
  • Ah, found this question which covers it http://stackoverflow.com/questions/68624/how-to-parse-a-query-string-into-a-namevaluecollection-in-net/ Flagged it. @Alex K., good idea using the implementation from system.web – MartinM Dec 12 '14 at 12:14
  • Here https://gist.github.com/bjorn-ali-goransson/b04a7c44808bb2de8cca3fc9a3762f9c –  Jul 03 '16 at 15:49
  • @fixagon For example, I'm writing a Xamarin Android app, I'd like to simply parse an url and get a token back from a redirect url for OAuth2 stuff, I'd like to not have to reference the entire System.Web assembly and have to ship that out with my app, that's perfectly reasonable in terms of not wanting to use System.Web. – Trevor Hart Dec 11 '17 at 19:21
  • 3
    This isn't a duplicate. It is explicitly asking for how to do this without using `System.Web`, which is how the other question handles it. – Jonathan Allen Apr 17 '18 at 05:04

1 Answers1

8

The HttpValueCollection you're using in your example is not actually trivial, and makes use of plenty of other parts of the System.Web library to encode a valid http url for you. It is possible to extract the source for the parts you need, but it would likely cascade into quite a bit more than you think!

If you understand that and simply want something primitive because you already ensure that the keys and values are encoded correctly, the easiest thing to do would be to just roll your own.

Here's an example, in the form of an extension method to NameValueCollection:

public static class QueryExtensions
{
    public static string ToQueryString(this NameValueCollection nvc)
    {
        IEnumerable<string> segments = from key in nvc.AllKeys
                                       from value in nvc.GetValues(key)
                                       select string.Format("{0}={1}", 
                                       WebUtility.UrlEncode(key),
                                       WebUtility.UrlEncode(value));
        return "?" + string.Join("&", segments);
    }
}

You could use this extension to build a query string like so:

// Initialise the collection with values.
var values = new NameValueCollection {{"Key1", "Value1"}, {"Key2", "Value2"}};

// Or use the Add method, if you prefer.
values.Add("Key3", "Value3");

// Build a Uri using the extension method.
var url = new Uri("http://baseurl.com/" + values.ToQueryString());
Adam Rhodes
  • 199
  • 6
  • 1
    Surround `key` and `value` with `WebUtility.UrlEncode()`. – Seva Alekseyev Jul 14 '17 at 15:07
  • @SevaAlekseyev - Done, good suggestion :) – Adam Rhodes Jul 17 '17 at 14:58
  • 2
    Why is this marked as the right answer when it does the exact opposite of ParseQueryString? – Jonathan Allen Apr 17 '18 at 05:05
  • @JonathanAllen Well, the title is poor and could do with an edit, but the body of the question is actually asking how to _build_ a query string and not _parse_ one. This confusion is due to the authors original approach which was to abuse the 'ParseQueryString' method to get an instance of the internal class 'HttpValueCollection' which just happens to also be a very convenient query builder. I'm not entirely sure if the author knew this was what they were doing, or shrugged it off as JFM. – Adam Rhodes Apr 17 '18 at 09:50
  • Thanks. This solution is a must for Unity 3D as it doesn't implement HttpUtility. – Guney Ozsan Oct 08 '18 at 19:22
  • 2
    I can't provide an answer because it's (erroneously) marked as dupe, but here is what I'm doing. I hope it helps someone. private Dictionary ParseQueryString(string url) { var querystring = url.Substring(url.IndexOf('?') + 1); var pairs = querystring.Split('&'); var dict = pairs.Select(pair => { var valuePair = pair.Split('='); return new KeyValuePair(valuePair[0], valuePair[1]); }) .ToDictionary((kvp) => kvp.Key, (kvp) => kvp.Value); return dict; } – spassvogel Nov 20 '18 at 10:31