HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Generic method for HTTP GET/POST parameter conversion

Submitted by: @import:stackexchange-codereview··
0
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:

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. 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.Nullable1[[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");   //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(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 2

Code 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);    //False
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;
}

Context

StackExchange Code Review Q#71475, answer score: 4

Revisions (0)

No revisions yet.