Saturday, February 4, 2012

Manipulating query string, the type safe way!

Our goal for today: Safe some valuable time.

Everyone who is developing for the web will come across the use of query string parameters.

SNAGHTML1a40b7f2

Handling these little buggers has proven to be quite time consuming.
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<FieldInfo> 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;
}
}
}

No comments: