4
\$\begingroup\$

I just made a method that should handle GET and POST parameters (primitive types) sent by AJAX requests to the server:

protected T GetParam<T>(string key) 
{
 string value = HttpContext.Current.Request[key];
 if (string.IsNullOrEmpty(value))
 return default(T);
 return (T)Convert.ChangeType(value, typeof(T));
}

Do you have any suggestions regarding improvements?

asked Dec 3, 2014 at 7:26
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

First point, small but important: give your method a proper name. GetParam doesn't mean much and doesn't tell what it returns. Take a name like GetValueFromParameter or GetHttpRequestValue.

Secondly, did you test this method properly? I changed the code a bit to be able to test it, I removed the HttpContext value and just use the parameter as value:

protected T GetHttpRequestValue<T>(string value) 
{
 if (string.IsNullOrEmpty(value))
 return default(T);
 return (T)Convert.ChangeType(value, typeof(T));
}

When I call it like this:

var longFromString = GetHttpRequestValue<long?>("0");

I get following exception:

Invalid cast from 'System.String' to 'System.Nullable`1[[System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.

I went looking for a cause and it seems that Convert.ChangeType has problems with nullable types. You have to use the underlying type of the nullable in order to make it work:

protected T GetHttpRequestValue<T>(string key) 
{
 string value = HttpContext.Current.Request[key];
 if (string.IsNullOrEmpty(value))
 return default(T);
 var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
 var convertedValue = (value == null) ? null : Convert.ChangeType(value, type);
 return (T)convertedValue ;
}

Now I get following results:

GetHttpRequestValue<long?>("0"); // 0
GetHttpRequestValue<long?>(""); // null
GetHttpRequestValue<long>("1"); // 1
GetHttpRequestValue<bool>("true"); // True
GetHttpRequestValue<bool>(""); // False
GetHttpRequestValue<long?>(null); //null
GetHttpRequestValue<bool>(null); //False

You also made your method dependent of an HttpContext, you cannot reuse it. Better would be to rename it to something like ConvertTo and leave out the HttpContext-line:

protected T ConvertTo<T>(string value) 
{
 if (string.IsNullOrEmpty(value))
 return default(T);
 var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
 var convertedValue = (value == null) ? null : Convert.ChangeType(value, type);
 return (T)convertedValue;
}

Example usage:

protected void Page_Load(object sender,EventArgs e)
{
 var value = HttpContext.Current.Request["YourKey"];
 var converted = ConvertTo<long?>(value);
}

Your code is still clean and the method is reusable. Notice that I use var instead of explicitly declaring variables. This is not mandatory, I just prefer to use it. Hope this helps!

Update:

I updated the method to handle a fail on the conversion, in case you want to change qwerty to a bool for example. :)

protected T ConvertTo<T>(string value) 
{
 if (String.IsNullOrEmpty(value))
 return default(T);
 var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
 T convertedValue = default(T);
 try
 {
 convertedValue = (T)Convert.ChangeType(value, type);
 }
 catch {}
 return convertedValue ;
}

This way of working swallows the exception. In case one occurs the default of T will be returned, otherwise the converted value. Results:

ConvertTo<int>("qwerty"); //0
ConvertTo<bool>("qwerty"); //False

Update:

As stated in the comments below, you can also take the code and throw it in an extension method. Also nice for reusability and your could will also look a bit cleaner. Here goes:

public static class Extensions
{
 public static T ConvertTo<T>(this string value) 
 {
 if (String.IsNullOrEmpty(value))
 return default(T);
 var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
 T convertedValue = default(T);
 try
 {
 convertedValue = (T)Convert.ChangeType(value, type);
 }
 catch {}
 return convertedValue ;
 }
}

Usage:

var intFromString = "2".ConvertTo<int>();
//intFromString is an integer with value 2
answered Dec 3, 2014 at 9:01
\$\endgroup\$
9
  • \$\begingroup\$ Oooh, looks like I didn't test it good enough. Thanks for your input - much appreciated! I noticed that my example use was wrong. Obviously I intended to pass the request key and not the value, just as you spotted... \$\endgroup\$ Commented Dec 3, 2014 at 9:03
  • \$\begingroup\$ Another note is that convertedValue will never be null in the ConvertTo method \$\endgroup\$ Commented Dec 3, 2014 at 9:07
  • \$\begingroup\$ @Johan if the parameter value is null or empty, null will be returned. Otherwise there will be a conversion to the desired type. Note that an exception will occur when the conversion fails, for example "qwerty" as a bool. \$\endgroup\$ Commented Dec 3, 2014 at 9:13
  • 1
    \$\begingroup\$ I'm smelling extension method potential here... \$\endgroup\$ Commented Dec 3, 2014 at 16:29
  • 1
    \$\begingroup\$ @JesseC.Slicer loved your comment, I was thinking the same. I updated my answe. :) \$\endgroup\$ Commented Dec 3, 2014 at 20:16
3
\$\begingroup\$

It looks good but not perfect IMHO.

  • you should use braces {} for single if statements also. This is just a matter of taste, but I prefer the use of it as it makes the code less errorprone.

  • The name of this method does not reflect what is happening. The code retrieves a value not a parameter, so a better name would be GetValue.

answered Dec 3, 2014 at 8:44
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.