I have a ASP.NET Web Forms project, and I want to build calls to .aspx pages in a strongly-typed fashion. I ended up rolling my own serializer that takes simple structs and saves them to/loads them from the query string. What do you think? Is my approach sane? Is there an accepted alternative I don't know about? Any feedback on the code?

Here's what building a call to a particular page looks like:

var fooParams= new FooPage.Parameters
{
    NodeID = nodeId,
    FooString = "the foo string"
};
string url = MyHelper.BuildCall(FooPage.URL, fooParams);
//url: ~/dir/FooPage.aspx?NodeID=5&FooString=the%20foo%20string

FooPage:

public partial class FooPage : System.Web.UI.Page
{
    public const string URL = "~/Dir/FooPage.aspx";
    public struct Parameters
    {
        public long? NodeID;
        public string FooString;
        public int? OtherParam;
    }

    protected Parameters Params;

    protected void Page_Load(object sender, EventArgs e)
    {
        Params = MyHelper.DeserializeFromNameValueCollection<Parameters>(Request.Params);

        //...
        //use Params.NodeID, Params.FooString, etc..
    }
}

Serialize/Deserialize to/from NameValueCollection:

public static void SerializeToNameValueCollection<T>(NameValueCollection nameValueCollection, T @object) where T : struct
{
    Type type = typeof(T);

    var fields = type.GetFields();
    foreach (var field in fields)
    {
        string key = field.Name;
        var value = field.GetValue(@object);

        if (value != null)
            nameValueCollection.Add(key, value.ToString());
    }
}

public static T DeserializeFromNameValueCollection<T>(NameValueCollection nameValueCollection) where T : struct
{
    T result = new T();

    Type type = typeof(T);

    var fields = type.GetFields();

    foreach (var field in fields)
    {
        string key = field.Name;

        string stringValue = nameValueCollection[key];
        if (stringValue != null)
        {
            object value;

            var baseType = Nullable.GetUnderlyingType(field.FieldType);
            if (baseType != null)
            {
                value = Convert.ChangeType(stringValue, baseType);
            }
            else
            {
                value = Convert.ChangeType(stringValue, field.FieldType);
            }

            field.SetValueDirect(__makeref(result), value);
        }
    }

    return result;
}

Format NameValueCollection into query string:

public static string BuildCall<T>(string url, T queryStringParams) where T : struct
{
    var queryStringBuilder = HttpUtility.ParseQueryString("");

    UrlHelper.SerializeToNameValueCollection(queryStringBuilder, queryStringParams);

    string queryString = queryStringBuilder.ToString();

    return url + "?" + queryString;
}
share|improve this question

1 Answer

up vote 1 down vote accepted

One of my favorite patterns for handling URL parameters in WebForms is the WebNavigator - http://polymorphicpodcast.com/shows/webnavigator/

If you're going through these kinds of Strongly-typed interactions for passing parameters between pages, maybe it is time you check out ASP .NET MVC - your solution looks a lot like model-binding.

share|improve this answer
This is great, I didn't know about the WebNavigator pattern! I would LOVE to use MVC (and MVC did inspire this approach), but unfortunately the product I'm working on can't afford the time it'd take to do the switch. – Daryl Mar 29 '12 at 4:56

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.