Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a query string for a URL in C#?

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?

like image 920
Boaz Avatar asked May 06 '09 11:05

Boaz


2 Answers

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)); 
like image 72
John Bledsoe Avatar answered Oct 14 '22 02:10

John Bledsoe


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...

like image 37
annakata Avatar answered Oct 14 '22 03:10

annakata