I\'m curious what everyone does for handling/abstracting the QueryString in ASP.NET. In some of our web apps I see a lot of this all over the site:
int val = 0;
I'm with the poster who suggested the helper methods (I would comment on his, but can't yet). Someone else disagreed with him in favor of creating properties, but my answer to that is that it doesn't gracefully handle the issue of checking for nulls or invalid formatting, etc. If you have helper methods, all that logic can be written once and centralized.
If you have a lot of pages, adding properties for each might be more time consuming than it is worth. But that's obviously just a preference, so to each his/her own.
One cool thing you could improve on the other poster's helper method is to make the out parameter a reference parameter instead (change out to ref). That way you can set a default value for the property, in case it is not passed. Sometimes you might want optional parameters, for instance -- then you can have it start with some default value for those cases where the optional parameter is not explicitly passed (easier than having a default value passed separately in). You can even add an IsRequired boolean parameter at the end, and have it throw an exception if the bool is set to true and the parameter is not passed. That can be helpful in many cases.
One thing is you're not capturing blank values here. You might have a url like "http://example.com?someKey=&anotherKey=12345" and in this case the "someKey" param value is "" (empty). You can use string.IsNullOrEmpty() to check for both null and empty states.
I'd also change "someKey" to be stored in a variable. That way you're not repeating literal strings in multiple places. It makes this easier to maintain.
int val = 0;
string myKey = "someKey";
if (!string.IsNullOrEmpty(Request.QueryString[myKey]))
{
val = int.Parse(Request.QueryString[myKey]);
}
I hope that helps!
Ian
Write some sort of a helper method (library) to handle it...
public static void GetInt(this NameValueCollection nvCol, string key, out int keyValue, int defaultValue)
{
if (string.IsNullOrEmpty(nvCol[key]) || !int.TryParse(nvCol[key], out keyValue))
keyValue = defaultValue;
}
Or something along those lines...
Here's what I came up with. It uses generics to return a strongly-typed value from the QueryString or an optional default value if the parameter isn't in the QueryString:
/// <summary>
/// Gets the given querystring parameter as a the specified value <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The type to convert the querystring value to</typeparam>
/// <param name="name">Querystring parameter name</param>
/// <param name="defaultValue">Default value to return if parameter not found</param>
/// <returns>The value as the specified <see cref="Type"/>, or the default value if not found</returns>
public static T GetValueFromQueryString<T>(string name, T defaultValue) where T : struct
{
if (String.IsNullOrEmpty(name) || HttpContext.Current == null || HttpContext.Current.Request == null)
return defaultValue;
try
{
return (T)Convert.ChangeType(HttpContext.Current.Request.QueryString[name], typeof(T));
}
catch
{
return defaultValue;
}
}
/// <summary>
/// Gets the given querystring parameter as a the specified value <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The type to convert the querystring value to</typeparam>
/// <param name="name">Querystring parameter name</param>
/// <returns>The value as the specified <see cref="Type"/>, or the types default value if not found</returns>
public static T GetValueFromQueryString<T>(string name) where T : struct
{
return GetValueFromQueryString(name, default(T));
}
Since writing this post I've written a very small class library for manipulating querystring values - see https://github.com/DanDiplo/QueryString-Helper
I tend to like the idea of abstracting them as properties. For example:
public int age {
get
{
if (Request.QueryString["Age"] == null)
return 0;
else
return int.Parse(Request.QueryString["Age"]);
}
}
You could add more validation if you wanted to. But I tend to like wrapping all of my query string variables this way.
EDIT: --- Also as another poster pointed out that you have to create these properties on every page. My answer is no you do not. You can create these properties in a single class that you can call "QueryStrings" or something. Then you can instantiate this class in every page where you want to access your query strings, then you can simply do something like
var queryStrings = new QueryStrings();
var age = queryStrings.age;
This way you can encapsulate all of the logic for accessing and handling each type of query variable in a single maintainable location.
EDIT2: --- And because it is an instance of the class, you could also use dependency injection to inject the QueryStrings class in every place you are using it. StructureMap does a good job of that. This also allows you to mock up the QueryStrings class and inject that if you wanted to do automated unit testing. It is much easier to mock this up than ASP.Net's Request object.
According to me, The best way to get querystring value is like following:
If the querystring is not found then the value of val
will be 0
.
int val = 0;
int.TryParse(Request.QueryString["someKey"], out val);