MartinM MartinM - 8 days ago 4
C# Question

Alternative to HttpUtility.ParseQueryString without System.Web dependency?

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?

Answer

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());