A common task when calling web resources from a code is building a query string to including all the necessary parameters. While by all means no rocket science, there are some nifty details you need to take care of like, appending an &
if not the first parameter, encoding the parameters etc.
The code to do it is very simple, but a bit tedious:
StringBuilder SB = new StringBuilder(); if (NeedsToAddParameter A) { SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA")); } if (NeedsToAddParameter B) { if (SB.Length>0) SB.Append("&"); SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); } }
This is such a common task one would expect a utility class to exist that makes it more elegant and readable. Scanning MSDN, I failed to find one—which brings me to the following question:
What is the most elegant clean way you know of doing the above?
You can create a new writeable instance of HttpValueCollection
by calling System.Web.HttpUtility.ParseQueryString(string.Empty)
, and then use it as any NameValueCollection
. Once you have added the values you want, you can call ToString
on the collection to get a query string, as follows:
NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty); queryString.Add("key1", "value1"); queryString.Add("key2", "value2"); return queryString.ToString(); // Returns "key1=value1&key2=value2", all URL-encoded
The HttpValueCollection
is internal and so you cannot directly construct an instance. However, once you obtain an instance you can use it like any other NameValueCollection
. Since the actual object you are working with is an HttpValueCollection
, calling ToString method will call the overridden method on HttpValueCollection
, which formats the collection as a URL-encoded query string.
After searching SO and the web for an answer to a similar issue, this is the most simple solution I could find.
.NET Core
If you're working in .NET Core, you can use the Microsoft.AspNetCore.WebUtilities.QueryHelpers
class, which simplifies this greatly.
https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers
Sample Code:
const string url = "https://customer-information.azure-api.net/customers/search/taxnbr"; var param = new Dictionary<string, string>() { { "CIKey", "123456789" } }; var newUrl = new Uri(QueryHelpers.AddQueryString(url, param));
If you look under the hood the QueryString property is a NameValueCollection. When I've done similar things I've usually been interested in serialising AND deserialising so my suggestion is to build a NameValueCollection up and then pass to:
using System.Linq; using System.Web; using System.Collections.Specialized; private string ToQueryString(NameValueCollection nvc) { var array = ( from key in nvc.AllKeys from value in nvc.GetValues(key) select string.Format( "{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)) ).ToArray(); return "?" + string.Join("&", array); }
I imagine there's a super elegant way to do this in LINQ too...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With