Manipulating query string, the type safe way!

Everyone who is developing for the web will come across the use of query string parameters. Handling these little buggers has proven to be quite time consuming.

SNAGHTML1a40b7f2

Our goal for today: Safe some valuable time.

Say we have: ../Default.aspx?PageNumber=1
Methods like Page.Request.QueryString[] are far from intuitive:

The old way:
public partial class _Default : Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
       int pageNumber;
       const string qsParam = "PageNumber";
       object qsObject = Page.Request.QueryString[qsParam];
       if (qsObject != null)
       {
           int qsValue;
           if (int.TryParse(qsObject.ToString(), out qsValue))
               pageNumber = qsValue;
           else
               pageNumber = -1;
       }
       else
           pageNumber = -1;
   }
}
The better way:
public partial class _Default : Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
       var queryString = new QueryStringParam();
       int pageNumber = queryString.PageNumber ?? -1;
   }
}

public class QueryStringParam : QueryStringParser
{
   public int? PageNumber;
}
Source code of QueryStringParser:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Specialized;
using System.Web;
using System.Reflection;

namespace Helpers
{
   public abstract class QueryStringParser
   {
       private NameValueCollection _queryString;

       private FieldInfo[] _fields;
       private IEnumerable Fields
       {
           get { return _fields ?? (_fields = GetType().GetFields()); }
       }

       protected QueryStringParser()
       {
           InitializeQueryString();
       }

       private void InitializeQueryString()
       {
           foreach (var fieldInfo in Fields) fieldInfo.SetValue(this, null);
           _queryString = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query);
           if (_queryString.Keys.Count > 0)
               foreach (string key in _queryString.Keys)
               {
                   var foundField = Fields.FirstOrDefault(cust => cust.Name == key);
                   if (foundField != null)
                   {
                       Object tempObject = null;
                       var value = _queryString[key];
                       var fieldType = foundField.FieldType;
                       try
                       {
                           if (fieldType == typeof(Guid?)) tempObject = new Guid(value);
                           if (fieldType == typeof(string)) tempObject = value;
                           if (fieldType == typeof(int?)) tempObject = int.Parse(value);
                           if (fieldType == typeof(bool?)) tempObject = bool.Parse(value);

                           // check for enum
                           var underlyingType = Nullable.GetUnderlyingType(fieldType);
                           if (underlyingType != null && underlyingType.IsEnum)
                               tempObject = Enum.Parse(underlyingType, value, true);

                           if (tempObject != null) foundField.SetValue(this, tempObject);
                       }
                       catch (Exception)
                       {
                       } // Can not convert querystring value into strongly typed parameter
                   }
               }
       }

       public override string ToString()
       {
           foreach (var field in Fields)
           {
               var fieldValue = field.GetValue(this);
               if (fieldValue != null)
                   _queryString[field.Name] = fieldValue.ToString();
               else
                   _queryString.Remove(field.Name);
           }
           string returnValue = String.Format("?{0}", _queryString);
           InitializeQueryString();
           return returnValue;
       }
   }
   public static class QueryStringParserExtensionMethods
   {
       public static bool HasValue(this string input)
       {
           return (!string.IsNullOrEmpty(input));
       }
       public static string Value(this string input)
       {
           return input;
       }
   }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s