Introduction
This article does not showing anything new but here I tried a new and efficient approach to implement Roles and Permissions into ASP.Net application. This article gives you introduction about Broser Files, Flag attribute for Enum, Control Adapters etc...
Background
You might be thinking that why am I submitting an Article on ASP.Net 2.0/3.5 in 2014. But some time situation is coming that you might have to work on existing applications which developed long back. Few weeks back we caught in a situation where we want to remove ages old Active Directory Profiles to Database level Roles and Permissions into existing application. We went through series of options and found this more efficient, scalable, maintainable way.
Using the code
We will see how to use Roles and Permission into Flags, Controller, ControlAdapter, BrowserFiles and UI Controls.
Enumerations and Flags
Enumeration type (Enum) is efficient way to define constants into integral form. Enums are not new to us and we might have used Enum at various places through our our code. A simple and perfect example of Enum is enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
As you know in above enum representation value for Sunday is starting with 0, and you may assign your own integer values to representing enum constants. And we are end up giving sequential values like 1, 2, 3 etc...
But do you know what if we want to represent multiple enum values, like meeting should be perform on either Tuesday or Thursday, then in above enumeration we have to represent multiple constant, but thanks to Power of 2, using assigning Enum Constant to Power of 2, we can represent multiple Enum constant through one value. In this example Insurance enum can be represent in below form in power of 2.
public enum Roles
{
Guest = 0,
BeginerPack = 1,
JumboPack = 2,
MegaPack = 4,
}
For above example when we will use Insurance myApplicableInsurance
= Permissions.Auto | Permissions.Peroperty it will return value 3, which represent Auto and Property with Binary OR. And myApplicableInsurance.ToString() represent as "1, 2".
Now consider a case, where you want to display on your page that what all Insurance can be possible or you want to use it in your controller with comma (,) separated, simply you just have to use Flag attribute on your Enum. like below code
[Flags]
public enum Permissions
{
Auto = 1,
Property = 2,
Health = 4,
Medical = 8
}
This way when you will use myApplicableInsurance.ToString(), it will return you "Auto, Property". You don't required string concatenation or format that's it.
Just imagine that this insurance details are associated with a logged in user and in your controller or business classes, you want to validate particular permission is applicable or not, simply you just have to write a static utility class and method which checks for applicable permission and you can use it wherever you want to use, like below code.
bool flag = AuthorizationUtility.IsAuthorized<<span style="font-size: 9pt;">Permissions</span><span style="font-size: 9pt;">>
Control Adapters
Control Adapters are available since ASP.Net 2.0 and well famous CSS Control Adapter Toolkit is available for extending style and property of controls based on conditions (like Browser, Machine etc...).
In this article we are trying to utilize Control Adapters to provide Permission based Authentication at Web Control levels.
Before jumping into Control Adapters and Browser file let we restrict WebPages so that not all WebPages trying to render for Control Adapters. This is not only improves the performance but also restrict coders to not to do mistake. And to implement this we will just add an empty Interface in our project, and let implement this in all WebPages for which we want to implement Authorization functionality.
interface ISecurable
{
}
We will use this interface logic to limit page renderization into our Control Adapter class.
Create a Control Adapter
Current ASP.Net framework is allowing to create an Adapter for all WebControls. A control adapter method must be extension of WebControlAdapter, which implements overridable OnLoad method.
public class ControlAuthorizationAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter
{
private void ManageWebControls(WebControl webControls)
{
}
[Obsolete("This is not supported, but I am researching on Adapter method for UserControls.")]
private void ManageUserControl(System.Web.UI.Control tb)
{
}
protected override void OnLoad(EventArgs e)
{
if (this.Page is ISecurable)
{
if (this.Control is WebControl)
this.ManageWebControls(this.Control as WebControl);
else if (this.Control is System.Web.UI.UserControl)
this.ManageUserControl(this.Control);
}
base.OnLoad(e);
}
}
Creating an Adapter method does not give guarantee that every controls will not loading through this method. You must need to register your control to Adapter from Browser File.
Create a Browser File
Some time in your project, you might need to do some functionality on Browser specific like Identification, CSS etc... If you have noticed then a App_Browsers directory is getting added into ASP.Net solution.
You need to add one Browser file into our solution, which needs to register adapter there. For each type of WebControl, you need to register them separately.
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType ="System.Web.UI.WebControls.Button" adapterType="AuthorizationControlTest.ControlAdapter.ControlAuthorizationAdapter" />
<adapter controlType ="System.Web.UI.WebControls.HyperLink" adapterType="AuthorizationControlTest.ControlAdapter.ControlAuthorizationAdapter" />
<adapter controlType ="System.Web.UI.WebControls.TextBox" adapterType="AuthorizationControlTest.ControlAdapter.ControlAuthorizationAdapter" />
</controlAdapters>
</browser>
</browsers>
Use Custom Attributes into Web Controls
We are almost ready to use our Control Adapter implementation, but to utilize for our functionality (Role/Permission based Authorization for Web Controls). We need to add little extra efforts.
We need to add custom attribute/property to WebControl in ASPX or ASCX file. We have identified "Permissions" as one kind of attribute. This attribute decides what should be applicable permissions for specific control. Like we have two buttons, which needs to enable/disable based on specific permissions.
Note: We have used Insurance into our example, so we will see permissions related to various insurances.
<asp:Button ID="Button1" runat="server" Text="Auto" Permissions="Auto"/>
<asp:Button ID="Button2" runat="server" Text="Property" Permissions="Property"/>
We will read this attribute "Permissions" into our Adapter class (in above "ManageWebControls" method). This method will read permission from attribute and matches against Role/Permissions and based on validation it will decide to enable/disable control.
To extend our example we can add one more attribute say "Property", this will decides whether you want to manage "Enable" or "Visiblity" of your controls.
Also for multiple permission check you can pass all applicable permissions with ',' (comma) separated.
<asp:Button ID="Button1" runat="server" Text="Auto" Permissions="Auto" Property="Enable"/>
<asp:Button ID="Button2" runat="server" Text="Property" Permissions="Property" Property="Visible"/><asp:Button ID="Button4" runat="server" Text="Health / Medical" Permissions="Health, Medical" />
Extend it to User Control
As I explained you earlier control Adapters can be only possible for WebControl, as current framework does not support for UserControl. But we have workaround over here. We can implement Above mentioned attributes as custom attribute into a user control and can assign it to child controls of UserControl.
public partial class InsuranceUpdate : System.Web.UI.UserControl
{
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
public string Permissions {get ; set ;}
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(this.Permissions))
foreach (Control ct in this.Controls)
if (ct is WebControl)
(ct as WebControl).Attributes.Add("Permissions", this.Permissions);
}
}
We can use it in our ASPX page in same way which we have used for WebControls.
<UC:ctrlInsureance id="ctrlInsureance1" runat="server" Permissions="Property">
Finally, we are ready for using Permission based Authorization of WebControls/UserControls into ASP.Net applications. But wait wait, what about applying Flags attribute for Enumerations, we have not used it. Not to worry, I am explaining it in next section.
Power of Flags Attribute
As we learned into beginning of this article that Flags attributes and Enum Constants with power of 2 allowing an Enumeration value into multiple form. like you can pass single Enum value to represent multiple enumeration constants. And a string representation of this Enum values gives comma separated Enum Constants.
In this section we will see how can we pass multiple form of Enumerations and how can we implement Authorization method in efficient way. This can be vary based on your structure of Role and Permissions but I tried to provide you as simple as possible. We will also use Generics to provide more flexibility.
public static class AuthorizationUtility
{
static AuthorizationRole[] authRoles;
static AuthorizationUtility()
{
}
public static bool IsAuthorized<T>(T flag)
where T : struct
{
return IsAuthorized<T>(flag.ToString());
}
public static bool IsAuthorized<T>(string flags)
where T : struct
{
Type type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException("The type parameter T must be an enum type.");
if (type.Equals(typeof(Permissions)))
{
}
else if (type.Equals(typeof(Roles)))
{
}
return false;
}
}
Now we are ready to utilize our Authorization method into various business and controller classes including ControlAdapters.
bool flag = AuthorizationUtility.IsAuthorized<Permissions>(Permissions.Health | Permissions.Medical);
MessageBox.Show("You are authorized to apply Medical Or Health Insurance");
Summary
Now we are ready run this project and after running it you will see that you are controlling your Web Controls and other functionality without a single If/Else condition. You will see benefit of this approach when you are working on enterprise applications and you have multiple controls. You can extend ControlAdapter based on your own requirements.
One you run your web page will look like below-
We have seen Enumerations & Flags, Browser Files, Control Adapters and Rules/Permission based Authorization on Web and User controls. I am not good expert in latest ASP.Net frameworks but it may possible that few frameworks are already supporting extension of Controls, like MVC provide AuthroizationAttribute at field level.
You can create your own Custom Control Library to deal with Roles/Permissions in better way, but remember, we were trying to deal with existing code structure where we want to implement Role/Permission based control functionality.
What Next
This can be extend to deal with User Control in better way, also we can implement controlling collections based on Roles and Permissions through Attributes and AttributeExtensions. I will work on it and will keep you updating on this Article.