Click here to Skip to main content
15,885,278 members
Articles / Web Development / ASP.NET
Article

Page Inheritance In ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.62/5 (20 votes)
18 Oct 20045 min read 176.3K   1.2K   86   15
Use object inheritance with System.Web.UI.Page to apply a common paradigm for user authentication, and extending the base web form feature set in your web application. Apply common security, specify per-page user access levels, and enforce common functionality, with only one line of code per page.

Introduction

The advent of ASP.NET arriving in a world that up to that point had become accustomed to VBScript or JavaScript spaghetti code was the introduction of true, or truer, object oriented programming (OOP) paradigms to web page development. We have seen over the years how to apply objects to facilitate web components and controls within ASP.NET applications to automate the process of building out a functional web solution with minimal code. One of the most overlooked features of object orientation, however, is utilizing inheritance with the base System.Web.UI.Page class.

The most important advantage base Page inheritance gives is the ability to enforce security across all pages that take advantage of the inheritance. You can even specify varying user access levels per page with only one line of code and one tweak of code. The tweak involves replacing the web form’s declaration with an inheritance of a new semi-abstract class called CommonPage rather than System.Web.UI.Page.

C#
// Create a new .cs file with a CommonPage class declaration
public class CommonPage : System.Web.UI.Page
{
    // ...
}

// Replace the standard inheritance declaration of any new web form
// with a reference to CommonPage
public class WebForm1 : CommonPage // changed ": System.Web.UI.Page"
{
    // ...
}

By moving to our own base class type, we are now able to customize the base functionality of every web form that inherits this base type, simply by modifying CommonPage.cs. In this way, all pages subscribing to this base class can also be guaranteed to expose and make available certain properties and methods not as easily available in the previous base class, such as application-specific page, user, or session properties. We can also enforce security checks and clean-up routines that are common across all participating pages.

Specifying Minimum Access Levels

The natural initial progression of extending CommonPage is to first enforce security. We can guarantee through inheritance and a simple security access level declaration that no user can access a particular page without proper security clearance as long as the page inherits CommonPage rather than System.Web.UI.Page. This is achieved by customizing the constructor of CommonPage and the Load event of System.Web.UI.Page, and thereby executing a new AccessCheck method before the web form ever executes.

C#
public CommonPage() {
    base.Load +=new EventHandler(CommonPage_Load);
}

private void CommonPage_Load(object sender, EventArgs e) {
    AccessCheck();
}

private void AccessCheck () {
    // enforce security here ...
}

At this point, it is now possible to customize the access levels of each page with only a single line of code per page. In order to do this, we must first define a set of access levels with an enum called AccessLevel.

C#
public enum AccessLevel {
    Guest = 0,
    BaseMember = 1,
    FullMember = 5, // numerically spaced for future expansion
    Administrator = 10
}

With AccessLevel defined, we can now specify a simple field in the web form called MinLevel that identifies the clearance level required for the particular web form. Normally, one would override a “MinLevel” property declared in CommonPage and customize its get method.

C#
public class WebForm1 : CommonPage
{
    protected override AccessLevel MinLevel {
        get {
            return AccessLevel.FullMember;
        }
    }
    // ...
}

This is, of course, considered the most correct way of customizing an access level customization on an inherited web form. However, in order to make this only a single line of code, we can break the paradigm of using overridden properties and instead use a constant field. In our case, our goal is to eliminate as much coding as possible, including even any method or property blocks. So, we instead declare a simple field in the web form that specifies the minimum access level.

C#
public class WebForm1 : CommonPage
{
   public const AccessLevel MinLevel = AccessLevel.FullMember;
   // ...
}

In order for CommonPage to retrieve this value, it must use the System.Reflection namespace to discover the value.

C#
// Figure 1
public class CommonPage : System.Web.UI.Page
{
    private const AccessLevel DefaultMinLevel = AccessLevel.Guest;
    private void AccessCheck() {
        AccessLevel minLevel = DefaultMinLevel;
        System.Reflection.FieldInfo fi =
            this.GetType().GetField("MinLevel",
            System.Reflection.BindingFlags.Public |
            System.Reflection.BindingFlags.Static |
            System.Reflection.BindingFlags.FlattenHierarchy);
        if (fi != null) minLevel = (AccessLevel)fi.GetValue(null);
        // ... 
    }
    // ...
}

Now, CommonPage knows the minimum access level for the page. We also specified a DefaultMinLevel constant to be sure that new inheriting web forms that do not have a MinLevel specification can default user access limits to this value. In this way, we can make the default access level FullMember, for instance, so that by default no new inheriting web form is accessible by anyone except that level of user.

Exposing a Common User Object

Now that we have specified an access level for a page, we need to have CommonPage map the user’s AccessLevel. The best way of doing this is to create a whole new user object and keep it stored in the session at all times. We will create an AppUser class and have its default AccessLevel property set to Guest. Then we will expose this object as a Session-stored property in CommonPage that is accessible as CurrentUser.

C#
// Figure 2
namespace InheritenceSample
{
    public class AppUser
    {
        public AccessLevel Level = AccessLevel.Guest;
    }

    public class CommonPage : System.Web.UI.Page
    {
        // ...

        public AppUser CurrentUser {
            get {
                AppUser usr = (AppUser)Session["AppUser"];
                if (usr == null) {
                    usr = new AppUser();
                    Session.Add("AppUser", usr);
                }
                return usr;
            }
        }
    }
}

At this point, it is very easy for AccessCheck method in CommonPage to determine whether the user does not have access to a particular page, with this boolean evaluation:

C#
if (CurrentUser.Level < minLevel) { // ...

By default, an AppUser object’s level is Guest. You can customize the AccessCheck method so that all Guest users attempting to access a more secure page are redirected to a login page that would modify the user’s access level according to a value specified in a database. In the login page, you can use Request.ServerVariables[“HTTP_REFERER”] to return to the referring page after logging in, or you can pass a more appropriate custom URL in the query string that redirects to the Login page, and have the Login page default to one and override to the other.

Going Further

In addition to applying security, this paradigm makes all new pages derived from your CommonPage class universally conformant to the parameters you specify in a single class, or in a few subclasses. For example, you can create a CommonXPage class that inherits CommonPage, and inherit CommonXPage only in web forms that do function X, so that these have a common minimum security level or a common task to perform when loading, and so forth.

We can also establish universal clean-up routines that are common to all pages in our application, by using the Unload event in CommonPage. (Note that utilizing deconstructors in ASP.NET, or “~CommonPage() {…}”, is not recommended.)

C#
public class CommonPage : System.Web.UI.Page
{
    public CommonPage() {
        base.Load += new EventHandler(CommonPage_Load);
        base.Unload += new EventHandler(CommonPage_Unload);
    }

    private void CommonPage_Unload(object sender, EventArgs e) {
        // common clean up ...
    }
    // ...
}

All of the benefits of inheritance in object oriented programming apply in ASP.NET. Hopefully, we have only scratched the surface as to what levels of productivity you can take web application development to using inheritance in ASP.NET and making the most of OOP methodologies.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Jon Davis is a software consultant with a passion and interest in Microsoft .NET technologies. He has been writing software since the age of six, and was an independent software consultant in the Central Valley of California for four years, after several earlier years as a software programmer with various companies in the San Francisco Bay Area.

Comments and Discussions

 
QuestionHow to access methods in the common page? Pin
User 333507311-Oct-07 1:07
User 333507311-Oct-07 1:07 
AnswerRe: How to access methods in the common page? Pin
User 333507311-Oct-07 1:09
User 333507311-Oct-07 1:09 
AnswerRe: How to access methods in the common page? Pin
adriancs5-Aug-13 17:27
mvaadriancs5-Aug-13 17:27 
QuestionSQL Session State Pin
gdycus2-Sep-06 12:18
gdycus2-Sep-06 12:18 
QuestionWhy not an Attribute? Pin
Marc Brooks26-Jan-05 5:51
Marc Brooks26-Jan-05 5:51 
AnswerRe: Why not an Attribute? Pin
Jon Davis5-Jul-06 20:55
Jon Davis5-Jul-06 20:55 
GeneralFor Visual Studio 2005, use Master Pages instead. Pin
Jon Davis2-Nov-04 10:02
Jon Davis2-Nov-04 10:02 
GeneralSuggestion: More simplicity for coder Pin
DaNiko31-Oct-04 22:40
DaNiko31-Oct-04 22:40 
GeneralRe: Suggestion: More simplicity for coder Pin
Jon Davis1-Nov-04 8:19
Jon Davis1-Nov-04 8:19 
GeneralVS.NET Designer Pin
Anonymous27-Oct-04 15:08
Anonymous27-Oct-04 15:08 
GeneralRe: VS.NET Designer Pin
Jon Davis1-Nov-04 8:27
Jon Davis1-Nov-04 8:27 
GeneralIntercepting events Pin
Richard Deeming27-Oct-04 5:49
mveRichard Deeming27-Oct-04 5:49 
GeneralRe: Intercepting events Pin
Jon Davis1-Nov-04 8:32
Jon Davis1-Nov-04 8:32 
GeneralRe: Intercepting events Pin
Richard Deeming1-Nov-04 23:58
mveRichard Deeming1-Nov-04 23:58 
GeneralRe: Intercepting events Pin
Jon Davis2-Nov-04 9:21
Jon Davis2-Nov-04 9:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.