views:

3147

answers:

5

If you have been looking for a nice and clean way to parse your query string values, I have come up with this:

    /// <summary>
    /// Parses the query string and returns a valid value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key">The query string key.</param>
    /// <param name="value">The value.</param>
    protected internal T ParseQueryStringValue<T>(string key, string value)
    {
        if (!string.IsNullOrEmpty(value))
        {
            //TODO: Map other common QueryString parameters type ...
            if (typeof(T) == typeof(string))
            {
                return (T)Convert.ChangeType(value, typeof(T));
            }
            if (typeof(T) == typeof(int))
            {
                int tempValue;
                if (!int.TryParse(value, out tempValue))
                {
                    throw new ApplicationException(string.Format("Invalid QueryString parameter {0}. The value " +
                                                              "'{1}' is not a valid {2} type.", key, value, "int"));
                }
                return (T)Convert.ChangeType(tempValue, typeof(T));
            }
            if (typeof(T) == typeof(DateTime))
            {
                DateTime tempValue;
                if (!DateTime.TryParse(value, out tempValue))
                {
                    throw new ApplicationException(string.Format("Invalid QueryString parameter {0}. The value " +
                                                         "'{1}' is not a valid {2} type.", key, value, "DateTime"));
                }
                return (T)Convert.ChangeType(tempValue, typeof(T));
            }
        }
        return default(T);
    }

I have always wanted to have something like that and finally got it right ... at least I think so ...

The code should be self explanatory ...

Any comments or suggestions to make it better are appreciated.

+4  A: 

Given that you only handle three different types, I would suggest three different methods instead - generic methods are best when they work well with every type argument which is permitted by the type constraints.

In addition, I would strongly recommend that for int and DateTime you specify the culture to use - it shouldn't really depend on the culture the server happens to be in. (If you have code to guess the culture of the user, you could use that instead.) Finally, I'd also suggest supporting a well-specified set of DateTime formats rather than just whatever TryParse supports by default. (I pretty much always use ParseExact/TryParseExact instead of Parse/TryParse.)

Note that the string version doesn't really need to do anything, given that value is already a string (although your current code converts "" to null, which may or may not be what you want).

Jon Skeet
+1 for ParseExact/TryParseExact especially as you can pass an array of formats.
Richard
+1  A: 

It seems to me that you are doing a lot of unecesary type convertions. The tempValue variables arere leady of the type you are trying to return. Likewise in the string case the value is already a string so just return it instead.

JohannesH
+1  A: 

In my application I've been using the following function:-

public static class WebUtil
{
    public static T GetValue<T>(string key, StateBag stateBag, T defaultValue)
    {
        object o = stateBag[key];

        return o == null ? defaultValue : (T)o;
    }
}

The required default is returned if the parameter has not been supplied, the type is inferred from defaultValue and casting exceptions are raised as necessary.

Usage is as follows:-

var foo = WebUtil.GetValue("foo", ViewState, default(int?));
AdamRalph
+1  A: 

A simple way to parse (if you dont want to do type conversions) is

 HttpUtility.ParseQueryString(queryString);

You can extract querystring from a URL with

 new Uri(url).Query
Simon_Weaver
A: 

I've written the following method to parse the QueryString to strongly typed values:

public static bool TryGetValue<T>(string key, out T value, IFormatProvider provider)
{
    string queryStringValue = HttpContext.Current.Request.QueryString[key];

    if (queryStringValue != null)
    {
        // Value is found, try to change the type
        try
        {
            value = (T)Convert.ChangeType(queryStringValue, typeof(T), provider);
            return true;
        }
        catch
        {
            // Type could not be changed
        }
    }

    // Value is not found, return default
    value = default(T);
    return false;
}
Ronald