Sometimes it is not easy for young developers to completely understand the power of the Reflection API and how it can be used in their ASP.NET applications. The approach is difficult and the documentation is very technical, so people prefer to write a lot of code to solve problems instead of implementing reusable features that could be used in several applications. In this article I share a utility that can be used to dynamically change ASP.NET WebControl attributes using Reflection and also show how this can be used by a simple website.
Why dynamically change attributes of a control? The reasons could be endless.
Some small applications may not implement security by role. Suppose, for enterprise issues, you need to protect some features of your application if the user's role isn't correct for the organization.
A quick solution could be to disable the controls (button, links, etc.)
that perform the function that you want to protect. Reflection a simple way to reach this goal.
Sometimes you need to change the attributes to the user control (like label text or colors) according to the user's choice. Reflection can help you.
A textbox of your UserControl can't be used in some pages but can be in other pages. Use Reflection to make the textbox disappear
without hundreds of "if" conditions.
These are just a few examples. Now let's go inside the code.
Using the Code
The example attached is entirely managed by the utility ReflectionComponent.
I will explain the most complete case. Looking at the code it will be easy to see the other features of the utility. Download the code and run it with "Default2.aspx" as the Start page. Click "How to use the sample" for help.
This application changes the "
enabled" attribute of webcontrols with several rules.
In the page you will see four areas (
SecondUserControl) representing the container controls. Selecting one or more in "Select Template" will enable the fieldsets "enable by Role" and "enable by control". These represent a set of rules you can apply to enable WebControls in areas you have chosen. You can:
Enable By Control: If you select, for example, the "Button" checkbox in the container controls you have chosen, you'll see the "Button" will be enabled and the Label (on the right)
ForeColor will be changed.
Enable By Role: If you select "Operator" from dropdownlist you'll see that only some controls in the container controls you have chosen will be enabled. This depends on the value of the custom attribute inserted inside the controls.
You can get this goal using ReflectionComponent in the App_Code folder by managing the parameter object that you pass when the static method
ManagedControls.ChangeControlsAttributeValues is called. Let's see how:
After you have selected areas, in "Enable by role", select "Operator". Note that each webcontrol in the controls container includes a custom attribute named
Security. In this example, in the control, when the value of "
Security" contains "
Operator" the attribute "
Enable" will be set to "
<asp:Button ID="btnOne" runat="server" Security="Administrator;Operator;Other" Text="Button" Enabled="False"
<asp:Label ID="lblBtnOne" runat="server" Text="(Disabled)" ForeColor="Red"></asp:Label><br /><br />
<asp:CheckBox ID="chkOne" runat="server" Security="Administrator;Operator" Text="CheckBox" Enabled="False"/>
<asp:Label ID="lblChkOne" runat="server" Text="(Disabled)" ForeColor="red"></asp:Label><br /><br />
<asp:TextBox ID="txtOne" runat="server" Security="Administrator" Enabled="False" ></asp:TextBox>
<asp:Label ID="lblTxtOne" runat="server" Text="(Disabled)" ForeColor="red"></asp:Label><br/><br/>
To get this goal you need to call the static method
of the utility with the correct parameters.
Look at the code in the
_managedControlParameter = new ManagedControlParameter();
Attribute = "Enabled",
AttributeNewValue = "true",
CustomAttribute = "Security",
CustomAttributeValue = ddlUserRoles.SelectedValue
ManagedControlParameter represents a set of parameters that the Reflection utility receive to do what you want. Examine it:
MainControls property represents the list of controls in the container you want to manage. However, you can only add a webcontrol if you
need to manage a single item. (See code in
Page_Prerender for a single
ManagedControls property are the webcontrols where you want to apply the new attributes. These are defined in the
ManagedControlType enum. The enum items must be the same
name of the webcontrols
(GetType().Name). In this example, you need to
apply the changes of all controls.
Attributes property includes a collection of
ManagedControlTypeAttributesValue in this object you define (
CustomAttributeValue will be omitted if you won't check it.)
Attribute: You want to change
AttributeNewValue: New value (be carefull about the type)
CustomAttribute: Attribute you want check
CustomeAttributeValue: Value you want to test
Next, call the
ChangeControlsAttributeValues method checks object parameters and reorganizes inputs in order to provide easy usability (
CheckParameters). After that, it retrieves the list of controls where changes will be applied (
GetManagedWebControls). See comments to
understand the rules to get the control list.
ApplyChange method starts to process the controls list. Next, for each control, try to apply the new attribute values you want to set. Using the Reflection method get a reference of the attribute that you need to modify and check if it is possible.
var controlAttribute = control.GetType().GetProperty(attribute.Attribute);
If you set
CustomAttribute, the method searches the attribute in the webcontrol (using
GetControlCustomAttributes) and checks its value. If OK,
controlProperty.SetValue will be used to set the new value. Be careful about the new value. The cast must be possible.
if (GetControlCustomAttributes(control)[attribute.CustomAttribute] != null &&
Reflection is a really powerful feature. This article is only a little sample
to demonstrate how you can improve the flexibility of your applications and solve some problems
quickly. Please send me feedback about that and sorry for my English.
Article Update Log
- 19 March 2013: Alignment of article code samples to utility code.
- 15 March 2013: Initial release.