Implement UI Role Awareness in Your Applications

Software applications often provide different functionalities to different users. For instance, an application will give an administrator role access to more features than it will to a typical user role. Changes to the application's user interface (UI) inevitably accompany these role-based changes in the application's functionality—and the UI changes may go beyond simple things such as enabling and disabling buttons. In fact, if role capability is different enough, an application may require a complete makeover. Whole sections of Web pages may disappear between roles, for example. Moving the positions of certain controls may be necessary when other controls are hidden from the user.

To implement UI changes based on role changes, you typically begin by implementing sets of user controls for your Web Forms. You could code separate Web Forms for each role, but why write redundant code when you can compose your page from user controls? Most likely, you will vary your role functionality by making user controls visible and invisible, or you will dynamically create user controls. To represent the different role-states, you normally implement enum values along with a switch statement to execute code based on the application's role-state. When a Web Form is loaded, each user control interrogates the current role-state and then executes the appropriate instructions based on the particular user control switch statement.

At this point, your solution contains a number of switch statements. For a small application, the number of switch statements does not result in a large amount of code. For a larger application with many user controls, the amount of code resulting from the switch statements can become significant. Common user controls save some coding, but how do you eliminate the repetitive switch statements? With an understanding of the controls collection and a little recursion, you can craft a solution with a single switch statement.

The Controls Collection

Utilizing the Controls collection on a Web Form page object is the first key to implementing the single switch statement solution. A Controls collection contains all of the child controls of a given control object. The control object is a base class for server controls, user control objects, and page objects. A Web Form page object is derived from a TemplateControl object, and a TemplateControl object is derived from the Control object.

A Controls collection implements the IEnumerable interface and, therefore, allows iteration using the foreach statement. The following is a simple example of iterating through the Controls collection on a server control object:

   foreach (Control cNext in c.Controls)
   (
      pv = new PageSecurityRoleSetup ();

      pv.SetupControl (lb, cNext,level+1);    //Recurse to next set
                                              //of sub-cont

      VisitTheControl (level, cNext);
   )

Interface Implementations

As stated previously, server controls, user controls, and Web Forms are all derived from the Control class. So, as you iterate through the Controls collection, how do you distinguish a regular server control from a control that implements role-state behavior? The answer lies in a C# operator.

C# has a simple but powerful operator called "is" that allows a developer to determine whether a class implements a particular interface or is derived from a particular class. The "is" operator can be used in if-then statements, as in the following example:

if (c is IPageUserSetup)
(
   WriteToList ("FOUND ONE: " + c.ToString(),level);

   ipagesetup = (IPageUserSetup)c;

   InvokeRoleSetup ( ipagesetup );
)

With the "is" statement, you have the following two options for separating .NET Framework server controls from server controls that must implement your role changes:

  1. Create a common base class (for user controls or Web Forms) that implements your role changes. All classes implementing role changes must be derived from this base class. Although perfectly acceptable, this solution is inflexible. C# allows you to derive a class only from one base class. Creating a single common base class may force you to create groups of intermediate common base classes. Common base classes also force you to create separate implementations for Web Forms and user controls.
  2. Create an interface. Like a class, an interface is a contract. A class derived from an interface must implement all of the properties and functions declared in the interface. Unlike the common base class solution, an interface is flexible. Derived user controls and Web Forms can both implement the same interface. An interface implementation would allow you the flexibility to implement Option #1 if a group of user controls behaved in a similar fashion.

The following is an example of a typical interface declaration:

public interface IPageUserSetup
(
   void DoSec1 ();
   void DoSec2 ();
)

Implement UI Role Awareness in Your Applications

Recursion: The Natural Approach

The Controls collection, C# "is" statement, and a common interface are clearly the tools for the job. However, you must circumvent one other complication before you have a complete solution: A Web Form can contain a number of user controls, and user controls can themselves contain layers of user controls and other server controls. How do you navigate all the user-control layers within a Web Form?

Invoking a function at the upper-most level and allowing the process to cascade downward to child, child-of-child, child-of-child-of-child, and so forth is a good approach. A straightforward, although not quite as good, way to execute the role-changes functions is to invoke the role-change function in the "Load" event of each Web Form or user control.

However, the most natural choice for navigating hierarchical or Binary-tree-like data structures like the layers of user controls on a Web Form is the recursive function. In the following example, the Web Form becomes the root node and the user controls on the form, along with the user controls on the Web Form's user controls, become the leaves in the tree:

public void SetupControl ( ListBox lb,Control c,int level )
(
   PageSecurityRoleSetup pv;

   pv = null;

   ListBox1 = lb;

   VisitTheControl (level, c);    //Visit the parent

   foreach (Control cNext in c.Controls)
   (
      pv = new PageSecurityRoleSetup ();

      pv.SetupControl (lb, cNext,level+1);    //Recurse to next set of
                                              //sub-controls

      VisitTheControl (level, cNext);
   )
)

The PageSecurityRoleSetup object creates an instance of another PageSecurityRoleSetup object when the SetupControl function is invoked. Once the controls at the deepest levels are visited, the recursive function terminates and the recursive process unwinds. The InvokeRoleSetup function calls the proper state-role function on the interface using a switch statement. The proper case statement is activated based on an enumerated value.

Implement Role Changes with a Single Switch Statement

Now you know an elegant and flexible solution for solving the role-change problem often encountered in Web sites with multiple user roles. Implementing role changes need not require scores of switch statements. By using the Controls collection and recursion, you can implement role changes with a single switch statement.

About the Author

Jeffrey Juday is a software developer with Crowe Chizek in South Bend, Indiana. He has been developing software with Microsoft tools for more than 12 years in a variety of industries. Jeff currently builds solutions using BizTalk 2004, ASP.NET, Sharepoint, and SQL Server 2000. You can reach Jeff at jjuday@crowechizek.com.



About the Author

Jeffrey Juday

Jeff is a software developer specializing in enterprise application integration solutions utilizing BizTalk, SharePoint, WCF, WF, and SQL Server. Jeff has been developing software with Microsoft tools for more than 15 years in a variety of industries including: military, manufacturing, financial services, management consulting, and computer security. Jeff is a Microsoft BizTalk MVP. Jeff spends his spare time with his wife Sherrill and daughter Alexandra.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

  • Agile methodologies give development and test teams the ability to build software at a faster rate than ever before. Combining DevOps with hybrid cloud architectures give teams not just the principles, but also the technology necessary to achieve their goals. By combining hybrid cloud and DevOps: IT departments maintain control, visibility, and security Dev/test teams remain agile and collaborative Organizational barriers are broken down Innovation and automation can thrive Download this white paper to …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds