asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search








Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Subclassing Pages and Master Pages in ASP.NET 2.0
By Wayne Berry
Rating: 3.9 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

     

    Sometimes the simplest things in ASP.NET 2.0 turn out to be the hardest things to implement. One example is trying to have a shared property across all your web pages. For example, let's say that you want to have a User object that is on all of your pages and that object be initialized on Page_Load. One way to do this is to have the same code in all your pages, like:

     

    Example 1:

    ---- page1.aspx.cs

    public partial class Page1 : System.Web.UI.Page
    {
        protected String _UserName;

        protected void Page_Load(object sender, EventArgs e)
        {
            _UserName = Session["UserName"].ToString();
        }
    }

    ---- page1.aspx.cs

    public partial class Page2 : System.Web.UI.Page
    {
        protected String _UserName;

        protected void Page_Load(object sender, EventArgs e)
        {
            _UserName = Session["UserName"].ToString();
        }
    }

    However, this is really repetitious, so instead let us subclass the System.Web.UI.Page class and create our own class to inherit all our pages from like:

    Example 2:

    ---- ParentPage.cs
    
    public class ParentPage : System.Web.UI.Page
    {
        protected String _UserName;
    
        public ParentPage()
        {
            this.Load += new System.EventHandler(this.Page_Load);
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            _UserName = Session["UserName"].ToString();
        }
    }
    
    ---- page1.aspx.cs
    
    public partial class Page1 : ParentPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
    }
    
    ---- page2.aspx.cs
    
    public partial class Page1 : ParentPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
    }
    

    Note that we need to add the Page_Load method in the ParentPage.cs to the loading event handler so that the method will get called when the page loads.

    Now we just need to use the _UserName in either of our pages, even though it is a protected member of ParentPage, the pages that subclass from that page can reach the member. However, other objects can change _UserName. This we get from inheritance.

    Let's use the _UserName in the first page when it loads.

    Example 3:

    ---- page1.aspx.cs
    
    public partial class Page1 : ParentPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    	Response.Write(_UserName);
        }
    }
    

    Here is where we run into the first problem. Because of the way that ASP.NET works you don't know which Page_Load will be called first. If the Page_Load for the Page1 class is called first, then _UserName will not be initialized yet. If the Page_Load for PageParent class is called first everything will work find. To solve this issue, all variables that we need for the pages need to be configured in the OnInit method, like this:

    Example 4:

    ---- ParentPage.cs
    
    public class ParentPage : System.Web.UI.Page
    {
        protected String _UserName;
    
        protected override void OnInit(EventArgs e)
        {
            // WWB: Allow The Base Class To Intialize First
            base.OnInit(e);
    
            _UserName = Session["UserName"].ToString();
        }
    }
    
    ---- page1.aspx.cs
    
    public partial class Page1 : ParentPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    	Response.Write(_UserName);
        }
    }
    

    This gives us control of the load order, since we are overriding a method, and not signing up for an event. If the page needs to use OnInit it can do so like this:

    Example 5:

    ---- ParentPage.cs
    
    public partial class Page1 : ParentPage
    {
        protected override void OnInit(EventArgs e)
        {
            // WWB: Allow The Base Class To Intialize First
            base.OnInit(e);
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(_UserName);
        }
    }
    

    Notice that Page1::OnInit class is calling ParentPage::OnInit, this allows us to "chain" the initialization. You could even use _UserName variable after the base.OnInit(e); if you wanted.

    One of the very nice features of ASP.NET 2.0 is master pages, let's add a master page to Page1 project, like this:

    Example 6:

    ---- page1.aspx.cs

    <%@ Page Language="C#" MasterPageFile="~/MasterPage1.master" AutoEventWireup="true" CodeFile="Page1.aspx.cs" Inherits="Page1" %>
    <asp:content id="Content" contentplaceholderid="ContentPlaceHolder1" runat="server">
    <%Response.Write(_UserName);%>
    </asp:content>

    ---- MasterPage1.master.cs

    public partial class MasterPage1 : System.Web.UI.MasterPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }

    Now let's set the title of the master page to the name of user, first lets modify ParentPage so that we can get __UserName property, we can do this like this:

    Example 7:

    -- ParentPage.cs
    
    public class ParentPage : System.Web.UI.Page
    {
        protected String _UserName;
    
        public String UserName
        {
            get { return (_UserName); }
        }
    
        protected override void OnInit(EventArgs e)
        {
            // WWB: Allow The Base Class To Intialize First
            base.OnInit(e);
    
            _UserName = Session["UserName"].ToString();
        }
    }
    

    Now all we have to do is modify the master page to set the title on page load. The code should look something like this:

    Example 8:

    --MasterPage1.master

    <%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage1.master.cs" Inherits="MasterPage1" %>
    <h1><asp:Label ID="lblTitle" runat=server></asp:Label></h1>
    <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
    </asp:contentplaceholder>

    --- MasterPage1.master.cs

    public partial class MasterPage1 : System.Web.UI.MasterPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            lblTitle.Text = Page.UserName;
        }
    }

    However, this will not compile, we get this error:

    'System.Web.UI.Page' does not contain a definition for 'UserName'

    This is because the 'System.Web.UI.Page' doesn't contain the UserName property, this property can only be found on the ParentPage class. So lets cast the Page property of the master page.

    Example 9:

    --- MasterPage1.master.cs 
    
    public partial class MasterPage1 : System.Web.UI.MasterPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            lblTitle.Text = ((ParentPage)Page).UserName;
        }
    }
    

    However, if we do this we need to make sure that only pages that inherit from ParentPage class use this master page, which is too restrict for us, so let's rearrange so that the Page calls the master page and sets the title to the user name

    Example 10:

    --- MasterPage1.master.cs
    
    public partial class MasterPage1 : System.Web.UI.MasterPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
    
        public void SetTitle(String title)
        {
            lblTitle.Text = title;
        }
    }
    
    ---- page1.aspx.cs
    
    public partial class Page1 : ParentPage
    {
        protected override void OnInit(EventArgs e)
        {
            // WWB: Allow The Base Class To Intialize First
            base.OnInit(e);
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            ((MasterPage1)Master).SetTitle(_UserName);
        }
    }
    

    This too requires a cast of the Master property, however this is much safer, because we know that the page is using Master1.master. Now it would be very nice to have ParentPage.cs set the title of the master Page.

    Example 11:

    ---- ParentPage.cs
    
    public class ParentPage : System.Web.UI.Page
    {
        protected String _UserName;
    
        public String UserName
        {
            get { return (_UserName); }
        }
    
        protected override void OnInit(EventArgs e)
        {
            // WWB: Allow The Base Class To Intialize First
            base.OnInit(e);
    
            _UserName = Request["UserName"].ToString();
             this.Load += new System.EventHandler(this.Page_Load);
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            ((MasterPage1)Master).SetTitle(_UserName);
        }
    }
    
    ---- page1.aspx.cs
    
    public partial class Page1 : ParentPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
    }
    

    However when we compile this we get this error:

    The type or namespace name 'MasterPage1' could not be found (are you missing a using directive or an assembly reference?)

    This is a confusing error message. We shouldn't need a assembly reference since all the pages are in the same project, and we are not missing a directive (#using) since all the pages are in the same namespace.

    The issue is that anything in /app_code (like PartentPage.cs) is in a different assembly that knows nothing about pages or master pages. Pages and master pages can "find" the assemblies in app_code. However, any classes in /app_code can't reference the classes that make up the pages and the master pages.

    The first idea is to move ParentPage.cs out of app_code, however this is impossible and doesn't work. So how do we make this work? We need to subclass System.Web.UI.MasterPage, creating a ParentMasterPage in app_code, like this:

    Example 12:

    ---- ParentMasterPage.cs
    
    public class ParentMasterPage : System.Web.UI.MasterPage
    {
        protected String _title;
    
    	public ParentMasterPage()
    	{
    	}
    
        public void SetTitle(String title)
        {
            _title = title;
        }
    }
    
    ---- ParentPage.cs
    
    public class ParentPage : System.Web.UI.Page
    {
        protected String _UserName;
    
        public String UserName
        {
            get { return (_UserName); }
        }
    
        protected override void OnInit(EventArgs e)
        {
            // WWB: Allow The Base Class To Intialize First
            base.OnInit(e);
    
            _UserName = Request["UserName"].ToString();
             this.Load += new System.EventHandler(this.Page_Load);
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            ((ParentMasterPage)Master).SetTitle(_UserName);
        }
    }
    
    ---- MasterPage1.master.cs
    
    public partial class MasterPage1 : ParentMasterPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            lblTitle.Text = _title;
        }
    }
    

    The ParentPage class can call the SetTitle method in ParentMasterPage class since both classes are both in app_code, instead of setting the asp:label in ParentMasterPage we set it to a property and any master pages that inherit from ParentMasterPage can access this variable. MasterPage1 class uses the _title property to set the label.

    The finished project in Visual Studio 2005 looks like this:

    Summary

    It might seem like a big deal to do all this subclassing and tweaking, however when done you have a very clean page, like Example 13, and master page that "knows" the user. This gives you a powerful base from which you can develop. It also lets you easily add additional "page wide" properties.

    Example 13:

    public partial class Page1 : ParentPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
    }
    

    About the Author

    Wayne Walter Berry founded Sign Me Up Marketing in 1996. As with all start-up companies, Berry is responsible for the design, product development, and strategy that drives this innovative high-tech company.

    As a former Microsoft design engineer, and the director of development for FreeShop, Berry's expertise includes software design, development, marketing and online business. The web site he created as a hobby to assist in distributing information to Active Server Page developers became his first product, 15 Seconds. The recent sale of 15 Seconds to Internet.com allowed Berry time to develop his latest product, XBuilder, and Kulshan.com, a community web-site for his hometown, Bellingham, Washington.

    The Bellingham native graduated from Bellingham High School, and Western Washington University with a BS in computer science. Berry is the author of three books, ActiveX Unleashed Programming, Windows Registry Guide, and Special Edition - Using Microsoft Internet Information Server 4.0. A popular and respected speaker, Berry recently spoke to the Professional ASP Developers Conference in Denver and has been invited to speak to an international ASP conference in Sweden.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Jul 21, 2005 - N-Tier Web Applications using ASP.NET 2.0 and SQL Server 2005 - Part 1
    While the .NET Framework made building ASP.NET applications easier then it had ever been in the past, .NET 2.0 builds on that foundation in order to take things to the next level. This article shows you to how to construct an N-Tier ASP.NET 2.0 Web application by leveraging the new features of ASP.NET 2.0 and SQL Server 2005.
    [Read This Article]  [Top]
    Apr 28, 2005 - New Files and Folders in ASP.NET 2.0
    With the release of ASP.NET 2.0, Microsoft has greatly increased the power of ASP.NET by introducing a suite of new features and functionalities. As part of this release, ASP.NET 2.0 also comes with a host of new special files and folders that are meant to be used to implement a specific functionality. This article examines these new files and folders in detail and provides examples that demonstrate how to utilize them to create ASP.NET 2.0 applications.
    [Read This Article]  [Top]
    Mar 10, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 2, Cont'd
    Alex Homer continues his detailed look at the major changes to the DataSet class. In this part, he looks at two features that allow developers to work with data in a more structured and efficient way when using the DataSet with a SQL Server 2005 database server.
    [Read This Article]  [Top]
    Mar 9, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 2
    Alex Homer continues his detailed look at the major changes to the DataSet class. In this part, he looks at two features that allow developers to work with data in a more structured and efficient way when using the DataSet with a SQL Server 2005 database server.
    [Read This Article]  [Top]
    Mar 3, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 1, Cont'd
    In this article, Alex Homer looks at the changes between the version 1.x and version 2.0 DataSet and their associated classes, showing you how you can take advantage of the new features to improve your applications' capabilities and performance.
    [Read This Article]  [Top]
    Mar 2, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 1
    In this article, Alex Homer looks at the changes between the version 1.x and version 2.0 DataSet and their associated classes, showing you how you can take advantage of the new features to improve your applications' capabilities and performance.
    [Read This Article]  [Top]
    Feb 16, 2005 - Writing a Custom Membership Provider for the Login Control in ASP.NET 2.0
    In ASP.NET 2.0 and Visual Studio 2005, you can quickly program custom authentication pages with the provided Membership Login controls. In this article, Dina Fleet Berry examines the steps involved in using the Login control with a custom SQL Server membership database.
    [Read This Article]  [Top]
    Dec 29, 2004 - ClickOnce Deployment in .NET Framework 2.0
    In this article, Thiru Thangarathinam examines .NET 2.0's new ClickOnce deployment technology that is designed to ease deployment of Windows forms applications. This new technology not only provides an easy application installation mechanism, it also eases deployment of upgrades to existing applications.
    [Read This Article]  [Top]
    Dec 15, 2004 - A Sneak Peek at ASP.NET 2.0's Administrative Tools
    With ASP.NET 2.0, Microsoft has made great strides in increasing developer productivity and has made implementing previously complex solutions relatively easy. Where this version of ASP.NET really shines, however, is in its new administrative tools that allow developers to spend less time managing the configuration of the servers and software and more time developing great code.
    [Read This Article]  [Top]
    Nov 17, 2004 - The ASP.NET 2.0 TreeView Control
    Thiru Thangarathinam introduces ASP.NET 2.0's new TreeView control which provides a seamless way to consume and display information from hierarchical data sources. The article discusses this new control in depth and explains how to use this feature rich control in your ASP.NET applications.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

    Solutions
    Whitepapers and eBooks
    Microsoft Article: HyperV-The Killer Feature in WinServer ‘08
    Avaya Article: How to Feed Data into the Avaya Event Processor
    Microsoft Article: Install What You Need with Win Server ‘08
    HP eBook: Putting the Green into IT
    Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
    Avaya Article: Setting Up a SIP A/S Development Environment
    IBM Article: How Cool Is Your Data Center?
    Microsoft Article: Managing Virtual Machines with Microsoft System Center
    HP eBook: Storage Networking , Part 1
    Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
    MORE WHITEPAPERS, EBOOKS, AND ARTICLES
    Webcasts
    Intel Video: Are Multi-core Processors Here to Stay?
    On-Demand Webcast: Five Virtualization Trends to Watch
    HP Video: Page Cost Calculator
    Intel Video: APIs for Parallel Programming
    HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
    Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
    MORE WEBCASTS, PODCASTS, AND VIDEOS
    Downloads and eKits
    Sun Download: Solaris 8 Migration Assistant
    Sybase Download: SQL Anywhere Developer Edition
    Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
    Red Gate Download: SQL Compare Pro 6
    Iron Speed Designer Application Generator
    MORE DOWNLOADS, EKITS, AND FREE TRIALS
    Tutorials and Demos
    How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
    eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
    IBM Article: Collaborating in the High-Performance Workplace
    HP Demo: StorageWorks EVA4400
    Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
    Microsoft How-to Article: Get Going with Silverlight and Windows Live
    MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES