patterncsharpMinor
Generic method for HTTP GET/POST parameter conversion
Viewed 0 times
genericconversionmethodpostgethttpforparameter
Problem
I just made a method that should handle GET and POST parameters (primitive types) sent by AJAX requests to the server:
Do you have any suggestions regarding improvements?
protected T GetParam(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?
Solution
First point, small but important: give your method a proper name.
Secondly, did you test this method properly? I changed the code a bit to be able to test it, I removed the
When I call it like this:
I get following exception:
Invalid cast from 'System.String' to 'System.Nullable
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:
Usage:
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(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("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(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("0"); // 0
GetHttpRequestValue(""); // null
GetHttpRequestValue("1"); // 1
GetHttpRequestValue("true"); // True
GetHttpRequestValue(""); // False
GetHttpRequestValue(null); //null
GetHttpRequestValue(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(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(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(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("qwerty"); //0
ConvertTo("qwerty"); //FalseUpdate:
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(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();
//intFromString is an integer with value 2Code Snippets
protected T GetHttpRequestValue<T>(string value)
{
if (string.IsNullOrEmpty(value))
return default(T);
return (T)Convert.ChangeType(value, typeof(T));
}var longFromString = GetHttpRequestValue<long?>("0");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 ;
}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); //Falseprotected 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;
}Context
StackExchange Code Review Q#71475, answer score: 4
Revisions (0)
No revisions yet.