Sociable

Monday, August 24, 2009

How to Parse a Query String without using the HttpUtility Class in System.Web

I wanted to remove the dependency on System.Web so that I could parse the query string of a ClickOnce deployment, while having the prerequisites limited to the "Client-only Framework Subset".

Here is a simple method that will accomplish this task.  I have also included some unit tests.  And, last but not least, I posted this on StackOverflow.  Thanks to rp for writing the initial method.

Code





  1. public static NameValueCollection ParseQueryString(string s)
  2.         {
  3.             NameValueCollection nvc = new NameValueCollection();
  4.             // remove anything other than query string from url
  5.             if(s.Contains("?"))
  6.             {
  7.                 s = s.Substring(s.IndexOf('?') + 1);
  8.             }
  9.             foreach (string vp in Regex.Split(s, "&"))
  10.             {
  11.                 string[] singlePair = Regex.Split(vp, "=");
  12.                 if (singlePair.Length == 2)
  13.                 {
  14.                     nvc.Add(singlePair[0], singlePair[1]);
  15.                 }
  16.                 else
  17.                 {
  18.                     // only one key with no value specified in query string
  19.                     nvc.Add(singlePair[0], string.Empty);
  20.                 }
  21.             }
  22.             return nvc;
  23.         \




Unit Tests





  1. [TestMethod]
  2.         public void ParseQueryString_OneNameValueParameter()
  3.         {
  4.             //
  5.             // TODO: Add test logic    here
  6.             //
  7.             const string queryString = "http://www.foo.com/testpage.htm?mykey=myvalue";
  8.             var result = Helper.ParseQueryString(queryString);
  9.             
  10.             Assert.AreEqual(1, result.Count);
  11.             Assert.AreEqual("myvalue", result["mykey"]);
  12.         }
  13.         [TestMethod]
  14.         public void ParseQueryString_ThreeNameValueParameter()
  15.         {
  16.             const string queryString = "http://www.foo.com/?mykey1=myval1&mykey2=myval2&mykey3=myval3";
  17.             var result = Helper.ParseQueryString(queryString);
  18.             Assert.AreEqual(3, result.Count);
  19.             Assert.AreEqual("myval1",result["mykey1"]);
  20.             Assert.AreEqual("myval2", result["mykey2"]);
  21.             Assert.AreEqual("myval3", result["mykey3"]);
  22.         }
  23.         [TestMethod]
  24.         public void ParseQueryString_OneKeyWithNoValue()
  25.         {
  26.             const string queryString = "http://www.foo.com/?mykey1";
  27.             var result = Helper.ParseQueryString(queryString);
  28.             Assert.AreEqual(1,result.Count);
  29.             Assert.AreEqual(string.Empty, result["mykey1"]);
  30.         }
  31.         [TestMethod]
  32.         public void ParseQueryString_MultipleKeysWithNoValue()
  33.         {
  34.             const string queryString = "http://www.foo.com/?mykey1=myval1&mykey2&mykey3=myval3";
  35.             var result = Helper.ParseQueryString(queryString);
  36.             Assert.AreEqual(3, result.Count);
  37.             Assert.AreEqual("myval1", result["mykey1"]);
  38.             Assert.AreEqual(string.Empty, result["mykey2"]);
  39.             Assert.AreEqual("myval3", result["mykey3"]);
  40.         }
  41.         [TestMethod]
  42.         public void ParseQueryString_NoUrlSpecifiedWithQueryString()
  43.         {
  44.             const string queryString = "mykey1=myval1&mykey2=myval2";
  45.             var result = Helper.ParseQueryString(queryString);
  46.             Assert.AreEqual(2, result.Count);
  47.             
  48.             Assert.AreEqual("myval1", result["mykey1"]);
  49.             Assert.AreEqual("myval2", result["mykey2"]);
  50.         \




2 comments:

Anonymous said...

Thanks, this was a great help. There is just on ething missing though. If the query string contains 'special characters, the routine does not decode that. The HttpUtility class does do that.

Thanks

Williamb said...

Thanks! Great helper class (I'm using it for WP7 Navigation) and I'm glad to see the unit tests :)