Using a Custom Base Class for your ASP.NET Pages' Code-Behind ClassesBy Scott Mitchell
One of the many benefits of object-oriented programming is that it allows for reuse of logic. For example, classes can be created that contain a base level of functionality. These base classes can then be extended through inheritance to create new classes that encompass the functionality of the base class along with any custom logic needed. The end result is that as a developer, once the base class has been created, you can extend and enhance the functionality of the base class with minimal effort. (For a more in-depth look at inheritance be sure to read Ian Stalling's article, Using Object-Orientation in ASP.NET: Inheritance.)
Since the .NET Framework is built upon the principles of object-oriented programming (OOP), it's no surprise that ASP.NET borrows
heavily from the tenets of OOP, one such tenet being inheritance. The base functionality for all ASP.NET pages is spelled out
Page class in the
System.Web.UI namespace. This class defines the essential properties, methods,
and events for an ASP.NET page, including such members as:
- The intrinsic objects -
Session, and so on,
- Common properties -
IsValid, and others,
- Methods used throughout the page lifecycle, such as
RaiseChangedEvents(), and others.
Pageclass, they need not be directly derived. That is, an ASP.NET page may extend a class that, itself, extends the
Pageclass. In fact, when using the code-behind model for creating ASP.NET pages the actual ASP.NET page is derived from the code-behind class, with the code-behind class being derived from the
In fact, oftentimes it makes sense to create a base class for a particular ASP.NET Web application that extends the
Page class and have all code-behind classes derive from this class, rather than directly from the
Page class. This universal base class can contain its own properties, methods, or events that are common to all pages
in the particular ASP.NET application, or it can extend the functionality of existing methods or properties. In this article
we'll look at how to create and start using a custom base class. Read on to learn more!
The Type Graph of ASP.NET Pages
ASP.NET pages have two core pieces: a markup section, which contains HTML markup and Web control syntax, and a source code portion. When using the code-behind model these two pieces are physically separated into two separate files. Alternatively, you can define the two pieces in the same file by using a server-side
<script>block. When creating a page using the code-behind model the code-behind class for the page must extend, either directly or indirectly, the
Pageclass. For example, the following shows the default code-behind class created in Visual Studio .NET when building a new ASP.NET page.
Regardless of whether the code-behind model or inline script model is used, when the
.aspx page is visited,
the ASP.NET engine translates the markup section into a class and then compiles that class.
If the code-behind model is being used, then the auto-generated class is derived from the page's corresponding code-behind class.
On the other hand, if the inline script model is being used then the auto-generated class is derived directly from the
Page class. The following diagram illustrates the resulting type graph used by both models.
Regardless of what model is being used, this auto-generated class's
responsibility is to create the page's control hierarchy and render the page's markup. This is possible because the auto-generated
class has the essential "guts" required to process an ASP.NET page as it is derived, either directly or indirectly, from the
Page class. Furthermore, the custom page-level logic - such as your
code in the
Page_Load event handler, a Button's
Click event handler, and so on - is present as well,
either in the auto-generated class's base class (if the code-behind model is being used) or was injected directly into the
auto-generated class (if the inline script block model is being used).
The point of this article, though, is not to be a thorough discussion of the page lifecycle. Rather, its intent is to focus on how to use a base class in an ASP.NET application to provide addition base logic for all ASP.NET pages. If you are interested in learning more about the page's lifecycle be sure to read Dino Esposito's article The ASP.NET Page Object Model or Solomon Shaffer's The ASP.NET Page Life Cycle.
The Basics of a Base Class
As the type graph examined above shows, the auto-generated ASP.NET page class must extend the
Pageclass, but can do so indirectly, through a code-behind class, for example. But there's no reason why there can only be one level of encapsulation between the auto-generated class and the essential
Pageclass. You can optionally create a base class from which all pages will derive from. When creating a base class, you'll typically have this base class extend the
Pageclass. If you are using the code-behind model your code-behind classes will need to be modified to inherit from the new base class as opposed to the
Pageclass. If you are using the inline script block model, you'll need to use the
Inheritskeyword to specify the type name of the class you want the auto-generated class to extend. With a custom base class the type graph for an ASP.NET page morphs into the one shown below:
As you can see in the type graph, the base class must derive from the
Page class. ASP.NET page's that want to
utilize the functionality of the base class will derive from this base class rather than from the
When creating a base class you might decide to add additional properties or methods, which are as simple as adding the appropriate
properties and methods to the base class itself. Additionally, you'll likely need to extend the functionality of the
Page class, adding logic at particular points in the page's lifecycle, such as common code that should run in
response to the
Load event. To accomplish this, you'll want to override the appropriate
OnInit to respond to the
OnLoad to respond to the
OnPreRender to respond to the
For example, if you needed the base class to perform some logic in the
Load event your base class's code
would look something like:
To have an ASP.NET page utilize the MyBaseClass base class you'd need to modify the code-behind class's syntax to
extend the custom base class rather than
If you are using Visual Studio .NET, the base class can be added to your ASP.NET project in one of two ways. The simplest option is to add a Class File to your ASP.NET project. To do this, right-click on the folder you want to add your project in the VS.NET Solution Explorer and choose to Add and then Add Class.
A better approach, in my opinion, is to add a new Class Library project to the Solution. To do this, right-click on the Solution in the Solution Explorer, select Add and choose New Project. Add a New Project of type Class Library in your language of choice. You can then add your base class to this new project. Finally, be sure to add a Reference from the Web application to the Class Library project by right-clicking on the Web application's References folder, selecting Add Reference. From the Add References dialog box, select the Projects tab and then add the Class Library project you just created.
Why Use a Base Class?
If you've been astutely reading along by this point you should have an understanding of the inheritance hierarchy of an ASP.NET page and know that it's possible to inject a custom base class into the hierarchy. The next natural question, though, is why would you want to do this? If you've never used a base class in this manner before, doing so sounds like a bit of extra work, so why bother?
A base class is advantageous if there is some common functionality needed to be required on every ASP.NET page in your Web application. That is, if you find yourself repeatedly copying and pasting the same snippet of code into most, if not all, ASP.NET pages in your application, you should seriously consider using a base class. With a base class you can define this common behavior in one spot. The ASP.NET page's that inherit from this base class, then, will automatically perform the needed functionality. If there needs to be a change to this common logic, you'll only need to change it in one place - the base class - as opposed to having to change the code in all the ASP.NET pages.
In one of the projects I'm working on I found myself adding the code discussed in Maintaining
Scroll Position on Postback to numerous pages through my site. Rather than having to add this code to each page, I quickly
decided to use a base class that would provide this common functionality. I added a Boolean
that defaulted to True, which indicated if the scroll position should be maintained on postback. In the
method I added the necessary client-side script (if
SmartScrolling was True).
Another example of using a base class can be seen in another article of mine, Working with Client-Side Script. In that article I examine how to create a base class that defines a number of methods for performing common client-side tasks, such as displaying popups, setting focus to an HTML element, displaying an alert, and so on. By putting such logic in a base class, any ASP.NET page in the application that derives from the base class can utilize any of the common client-side tasks by calling the appropriate method (as opposed to having to emit the necessary script directly from the ASP.NET page's code-behind class).
|Useful Base Page Class Functionality|
One of the challenges of getting started using a base page class is that it's not entirely clear what goes in it. A custom base page class
usually contains a mix of application-specific logic and more general useful page-level functionality that is not included in the
In this article we examined the type graph of ASP.NET pages and saw how the base functionality of ASP.NET pages could be further customized for a particular ASP.NET application through the use of a base class. It is essential that all ASP.NET pages derive, either directly or indirectly, from the
Pageclass in the
System.Web.UInamespace. However, rather than having your code-behind classes derive from
Page, in many scenarios it makes sense to create your own base class that derives from
Page, having the code-behind classes derive from the base class. With this approach, any logic common to all pages can be placed within the base class.