Read Asp.net Request Param and Session dynamically into properties

This Article shows how you can use Attributes and Reflection to dynamically populate property with value from param, session or context without writing any addition code. I have used this technique in past and I hope you will also find it useful.


Introduction:

 

This article shows how you can use Attributes and Reflection to dynamically populate property with value from param, session or context without writing any addition code. I have used this technique in past and I hope you will also find it useful.

 

Why do I need this?

 

I am a lazy programmer, I won't write a code that I do not have to, I also believe that amount of mistakes that I make while writing code is directly proportional to number of lines of the code that I write.

Why would I write following code?

 

public int id;

public string userName;

 

void Page_Init(object sender, EventArgs e)

{

    if (!string.IsNullOrEmpty(Request.QueryString["id"]))

    {

        id = int.Parse(Request.QueryString["id"]);

    }

 

    if (Request.Cookies["userName"] != null && Request.Cookies["userName"].Value != null)

    {

        userName = Request.Cookies["userName"].Value;

    }

}

 

If I can just write following.

[PageProperty]

public string id;

[PageProperty(ReadFrom = DictionaryType.Cookie)]

public string userName;

 

Lets define what are we interested in reading:

 

Most common place where we need to read data is query string dictionary but we will also read from additional places like Form, Session, Cookie, Headers and Dictionary that comes with Context. We will create flag that will define places that we can read data from.

 

[flags]

public enum DictionaryType

{

    QueryString = 1,

    Form = 2,

    Session = 4,

    Context = 8,

    Cookie = 16,

    Header = 32,

}

 

Next step will be to create Attribute class for our properties and fields:

  1. Attributes provide a powerful method of associating declarative information with code. We need two properties in our attribute.
  2. Key which we need to pass to read data from dictionary, If user do not provide this key then we will assume that name of property/field is key.

Enumeration that defines dictionary to read data from which will default to query string. 

 

public class PageProperty : Attribute

{

    private DictionaryType readFrom = DictionaryType.QueryString;

    privatestring key;

 

    publicstring Key

    {

        get

        {

            return key;

        }

        set

        {

            key = value;

        }

    }

    public DictionaryType ReadFrom

    {

        get

        {

            return readFrom;

        }

        set

        {

            readFrom = value;

        }

    }

}

 

Once we have above class we can tag fields in our page with above attribute.

 

[PageProperty(ReadFrom = DictionaryType.Cookie)]

public int userId;

Reading attributes using reflection and populating values:
  1. We will use reflection to inspect page class to find all property or public fields with PageProperty Attribute.
  2. Next step will be to get key and DictionaryType.
  3. And once we know source and target to populate and we will get information from appropriate dictionary and populate it.

We will warp this logic into a small static class with static Read method, which takes reference of page object.

 

public static void Read(object pageObject)

{

    // read for all fields.

    FieldInfo[] fields = (pageObject.GetType()).GetFields();

    foreach (FieldInfo fieldInfo in fields)

    {

        object[] attributes = fieldInfo.GetCustomAttributes(typeof(PageProperty), false);

 

        if (attributes.Length > 0)

        {

            PageProperty pageProperty = attributes[0] as PageProperty;

            string key = pageProperty.Key;

            if (key == null) key = fieldInfo.Name;

 

            object val = getValue(key, pageProperty.ReadFrom);

            if (val != null)

            {

                fieldInfo.SetValue(pageObject, changeType(val, fieldInfo.FieldType));

            }

        }

    }

}

 

Retriving value from Dictionary:

 

Since we are using flags user might specify more than one place to read from, for example user might specify following:

 

[PageProperty(ReadFrom = DictionaryType.QueryString | DictionaryType.Cookie)]

 

To handle this we will go through all selected enumerations and return first with value, so in above mentioned example if query string value was present it will return query string value, otherwise it will return value from cookie.

 

private static object getValue(string key, DictionaryType readFrom)

{

 

    if ((readFrom & DictionaryType.QueryString) == DictionaryType.QueryString &&

    HttpContext.Current.Request.QueryString[key] !=null)

    {

        return HttpContext.Current.Request.QueryString[key];

    }

 

    elseif ((readFrom & DictionaryType.Form) == DictionaryType.Form &&

    HttpContext.Current.Request.Form[key] !=null)

    {

          return HttpContext.Current.Request.Form[key];

    }

}

    
How to use Property Reader in your web page?

  1. Drop Jigar.Web.PagePropertyReader.dll in to bin directory of your web project.
  2. In your Page class add following line in Pre_Init Event.
    PropertyReader.Read(this);
    Alternatively you can also create PageBase class by inheriting from System.Web.UI.Page and override PreInit event.
  3. Finally in your page just create public property or field with PageProperty Attribute and you are done.

Source code includes sample web application, which shows usage of PropertyReader. It also includes test page with different senerios.

 

What about performance cost associated with reflection?

 

Reflection is definitely going to add some performance cost to your application, you will have to analyze value vs. cost analysis for your application and decide best for you.

Instead of reflection you might also want to try using Reflection.Emit to improve performance.