Role aware ASP.NET web controls
A common feature I’ve found necessary for web applications is role-based security at the field level. For example, I may have a form that allows editing a user’s information. The requirements may include the rule that only certain types (roles) may edit certain fields.
This can be accomplished in myriad ways. You can create a different form per role, and direct the user to the appropriate form. Or you can put specific logic around each relevant field to show, enable, or hide each field.
Both these routes can lead to a lot of extra coding, and even more maintenance. I’d like to be able to tell each affected field to display itself correctly based on the user’s role.
The Microsoft.NET Framework 2.0 introduced the Membership and Roles framework and the Microsoft Provider Model, which gives us an API-based way to interface with users and roles. If you use a RoleManager (either one of the defaults provided or your own custom implementation), the following code gives an example of how you can extend the existing WebControls to render themselves based on a current user’s roles.
using System.Web.UI; using System.Web.UI.WebControls; using System; using System.ComponentModel; namespace RoleAwareServerControls { /// /// Role Aware Text Box. Will only render as Enabled if user is /// in the in the RoleName. /// [DefaultProperty("Text")] [ToolboxData("<{0}:RoleAwareTextBox runat=server RoleName=user></{0}:RoleAwareTextBox>")] public class RoleAwareTextBox : System.Web.UI.WebControls.TextBox { private bool visibleIfUnauthorized; /// /// if user is not in role, should the field be displayed at all? /// public bool VisibleIfUnauthorized { get { return visibleIfUnauthorized; } set { visibleIfUnauthorized = value; } } private String roleName; /// /// if user is in this role, enable this field, else not /// public String RoleName { get { return roleName; } set { roleName = value; } } /// /// determine if TextBox should be Enabled or Visible /// ///An EventArgs /// that contains the event data. protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); // assume normal display if RoleName not set if (!String.IsNullOrEmpty(roleName)) { Enabled = (Page.User.Identity.IsAuthenticated && Page.User.IsInRole(roleName)); Visible = Enabled ? true : visibleIfUnauthorized; } } } }
To use the new web control, register it with your page (or for the whole application in your web.config) and add it to the page:
<%@ Page Language="C#" MasterPageFile="~/Site.master"
AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" Theme="Default" %>
<%@ Register TagPrefix="rasc" Namespace="RoleAwareServerControls" %>
<body>
<form id="form1" runat="server">
<rasc:RoleAwareTextBox runat="server" ID="textBox"
RoleName="administrator" VisibleIfUnauthorized="true" >
Hi, administrator</rasc:RoleAwareTextBox>
</form>
</body>No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
5 Responses to “Role aware ASP.NET web controls”.
Simple, clear and easy solution
Here’s an improvement.
This allows the user to be in multiple roles,
Set the RoleNames on the control to a comma seperated list
Abstract the checker out so that its easier to write the controls
// Example Control override
namespace BarrettJackson.RoleAwareServerControls
{
[DefaultProperty("Text")]
[ToolboxData(@"")]
public class RoleAwareImageButton : System.Web.UI.WebControls.ImageButton
{
private string _roleNames;
public string RoleNames
{
get { return _roleNames; }
set { _roleNames = value; }
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
RoleChecker.CheckRole(this, _roleNames, Page.User);
}
}
}
// abstract out the turning on and off of the contro
using System.Web.UI;
using System.Web.UI.WebControls;
using System;
using System.ComponentModel;
namespace BarrettJackson.RoleAwareServerControls
{
public static class RoleChecker
{
public static void CheckRole(Control ctrl, string roleNames, System.Security.Principal.IPrincipal user)
{
ctrl.Visible = false;
if (!user.Identity.IsAuthenticated)
{
ctrl.Visible = false;
return;
}
if (!String.IsNullOrEmpty(roleNames))
{
if (roleNames.Trim() == “*”)
{
ctrl.Visible = true;
return;
}
string[] split = roleNames.Split(‘,’);
foreach (string role in split)
{
if (user.IsInRole(role.Trim()))
{
ctrl.Visible = true;
break;
}
}
}
else
{
ctrl.Visible = true;
}
}
}
}
// implimentation in an aspx page
Nice modification, Mark! Thanks for sharing it.
An Even Better version much more atomic implimentation a hybrid of both
Example Control:
public class RoleAwareButton : System.Web.UI.WebControls.Button
{
private string _roleNames;
public string RoleNames
{
get { return _roleNames; }
set { _roleNames = value; }
}
private bool _visibleIfUnauthorized;
public bool VisibleIfUnauthiorized
{
get { return _visibleIfUnauthorized; }
set { _visibleIfUnauthorized = value; }
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
this.Enabled = (RoleChecker.CheckRoles(_roleNames, Page.User) && Page.User.Identity.IsAuthenticated);
this.Visible = this.Enabled ? true : _visibleIfUnauthorized;
}
Example RoleChecker class
public static class RoleChecker
{
public static bool CheckRoles( string roleNames, IPrincipal user)
{
bool isInRole = false;
if (String.IsNullOrEmpty(roleNames.Trim()) || (roleNames.Trim().CompareTo(“*”) == 0))
{
isInRole = false;
return isInRole;
}
string[] split = roleNames.Split(‘,’);
foreach (string role in split)
{
if (user.IsInRole(role.Trim()))
{
isInRole = true;
break;
}
}
return isInRole;
}
}
Also the advantage is including the controls in your project you get the RoleChecker static class included also so you can use the RoleChecker.CheckRoles(string _roleNames, System.Security.Principal.IPrincipal user); method anywhere in the project.
Leave a comment.