Skip navigation

Take Advantage of Visual Inheritance in ASP.NET

Build Web pages from other ASP.NET pages.

CoreCoder

 

LANGUAGES: C#

TECHNOLOGIES: Codebehind | Page Inheritance

 

Take Advantage of Visual Inheritance in ASP.NET

Build Web pages from other ASP.NET pages.

 

By Dino Esposito

 

I'm going to start this installment of my column by talking a little about Windows Forms. Yes, even though this is asp.netPRO. I've got a good reason, though. Trust me, and follow along.

 

For Windows Forms, visual inheritance refers to the .NET Framework's ability to create new forms from previously created forms via inheritance. The .NET Framework provides a base class named Form that you extend in user projects by adding child controls. Each application form is an instance of some user-defined class that inherits from Form. To make all your applications share the same look and feel, you could create a class-inheriting form, add particular features and controls, and compile the resulting class into a new assembly.

 

This feature isn't rocket science - in fact, you can think of it simply as a derivation of class inheritance. The "visual" in visual inheritance emphasizes the fact that all visual controls (buttons, listboxes, grids, etc.) are implemented merely as protected properties within the class interface; a derived class receives all protected and public properties irrespective of type. Thus the only difference between visual inheritance and OOP inheritance is that Visual Studio .NET generally hides the auto-generated code that renders controls through properties, providing a glimpse into visual derivation.

 

By now you're probably wondering, "Where are you leading us with this Windows Forms introduction?" Well, it's relevant because ASP.NET pages function similarly. The .NET Framework allows you to create new Web forms from existing ones.

 

Create Pages

Visual inheritance works in more than Windows Forms applications. In fact, it is supported in Web forms already, although referred to with a different name - codebehind. Although the MSDN documentation presents the code-behind feature as a way to keep layout and code in separate files, it never mentions visual inheritance. Nevertheless, the key thing going on beneath code-behind implementation is page inheritance.

 

Just as Windows Forms applications inherit - directly or indirectly - from the Form base class, all Web Forms applications are built atop the Page class. When the ASP.NET runtime processes the content of a given URL, it transforms the page into a living instance of a dynamically created class whose name is determined from looking at the URL. If the page is called index.aspx, the class name will be ASP.index_aspx:

 

namespace ASP

{

  public class index_aspx : Page

  {

     :

  }

}

 

All the public members defined in the script block are defined as methods and properties of the new class with the same level of visibility declared. Created as a VB or C# temporary file, the index_aspx class is compiled on the fly and stored as an assembly in the ASP.NET cache on the Web server machine. Any request after the first is resolved by instantiating the index_aspx class from the local assembly. If the time stamp of the index.aspx page changes, the dependency between the URL and the assembly gets broken. As a result, the next request for the index.aspx causes the page to compile again.

 

As you are aware, an ASP.NET page is articulated into three sections: directives, script, and layout. Directives contain instructions for the compiler, such as the command-line switches to use and language of choice for the dynamic class. The script section sets the programming interface for the new class. (By the way, the fact that the content of the script is merged into a new source file is the reason you can use only one language in ASP.NET.) The layout is parsed and each element node is transformed into a control. Plain text is rendered into a LiteralControl. The whole layout code works as input to an internal procedure that builds the page tree of controls. In other words, the layout of the ASP.NET page is processed at compile time, transforming each element into a .NET Web server control. This is not much different from what happens with Windows forms in which each control dropped into the form is rendered as a property of that control type.

 

If you want to see the source code of a compiled ASP.NET page, set the debug attribute to True on the @Page directive and run the page. Next, go under this path and search the subdirectories for a .cs or .vb file, where you will find only one source file - yours:

 

C:\WINNT\Microsoft.NET\Framework\

   v1.0.3705\Temporary ASP.NET Files

 

In this article's source code, I also have included the compiled version of one of the sample pages for your perusal (see the Download box at the beginning of this article for details).

 

Retargeting Codebehind

OK, all this stuff about the page creation is interesting, but what does it have to do with visual inheritance? Any ASP.NET page runs as a living instance of a class that inherits from the Page class. The Page class simply is a base class with no special built-in functions. If you could replace Page with a more specific class, you actually could give your final pages additional features and functionalities; this is the gist of software inheritance.

 

Not only can your own base page provide extra properties, methods, and predefined behaviors, but it can dispense images and controls as well. This kind of inheritance is not very visual because there is no easy or system-provided way to transform the source of an .aspx file into an equivalent Visual Basic .NET or C# class. (Paradoxically, this is what the ASP.NET runtime accomplishes, but this function is unavailable as a separate tool. Writing such a utility would not be difficult, especially once you take a look at what the system runtime generates.)

 

Codebehind is the ASP.NET feature that allows you to set the base class for the page explicitly. This is what codebehind is really for. Architecturally speaking, the most touted aspect of codebehind - that is, the separation you obtain between code and layout - is more of a side effect. To support my position that code separation is not the primary aspect of codebehind, consider that you easily can write a code-behind page that contains server-side code in the script section. And so the feature designed to separate code and layout paradoxically permits you to merge code and layout in a single file.

 

Amazingly (but not surprisingly), using code-behind pages with server code in the .aspx file allows you to mix different languages within the same ASP.NET page. In fact, the codebehind class is compiled into an assembly and thus becomes a language-neutral component. The final .aspx page is rendered through another class written in any language that inherits from the compiled class. Figure 1 demonstrates how the ASP.NET runtime creates the class that actually represents the page being processed.


Figure 1. A code-behind page relies on a compiled class for back-end processing. Because this class is compiled independently from the final page class, you can write it in any .NET language. If you insert local code in the .aspx file, it would be used to enrich the dynamically created class - as such, you can code it in another .NET language.

 

The code-behind feature, then, allows you to specify the base class from which the final page class, created dynamically during the first request, will inherit. You may supply the code-behind class as a source file or via a compiled assembly. Although codebehind is more documented as a feature to separate code and layout within the context of an ASP page, it is the key tool utilized in the implementation of Windows Forms-like visual inheritance for Web forms. Let's see an example.

 

ASP.NET Visual Inheritance

You link an .aspx page to a code-behind class using the Inherits attribute on the @Page directive:

 

<%@ Page Language="C#"

    Inherits="AspNetPro.CoreCoder.CompanyBasePage" %>

 

The Inherits attribute points to the name of the class to be employed. If the class is compiled into an assembly, make sure the assembly is available either within the global assembly cache (GAC) or in the virtual directory's .bin subfolder. Alternately, you may specify the source file of the code-behind class through the Src attribute:

 

<%@ Page Language="C#"

    Inherits="AspNetPro.CoreCoder.CompanyBasePage"

    Src="CompanyBasePage.cs" %>

 

Of course, if your goal is to set up a hierarchy of page classes for use throughout a company's projects, you might want to use the first approach and compile the classes to an assembly. In terms of performance, the difference is minimal because the source file is compiled into a local assembly upon the first call. So after the first call, the performance is identical.

 

The code in Figure 2 shows the key parts of the sample code-behind class.

 

namespace AspNetPro

{

   namespace CoreCoder

   {

   using System;

   using System.Web.UI;

   using System.Web.UI.HtmlControls;

   using System.Web.UI.WebControls;

   using System.Collections.Specialized;

 

   public class CompanyBasePage : Page

   {

      public String baseURL = "";

      public AutoLinks Links;

      public bool ShowHeader = true;

      public bool ShowTitleBar = true;

 

      protected override void OnInit(EventArgs e)

      {

         base.OnInit(e);

         Links = new AutoLinks();

      }

 

      protected override void OnLoad(EventArgs e)

      {

         base.OnLoad(e);

 

         if (ShowHeader)

             BuildPageHeader();

 

         if (ShowTitleBar)

            BuildTitleBar();

               }

   

               protected void BuildPageHeader()

               {

               Table thePageHeader = new Table();

 

               // code here to populate the table

               // (see source)

 

               PlaceHolder ph = (PlaceHolder)

                FindControl("PageHeader");

                  ph.Controls.Add(thePageHeader);

               }

   

               protected void BuildTitleBar()

                {

                  Table theTitleBar = new Table();

   

               // code here to populate the table

               // (see source)

 

               PlaceHolder ph = (PlaceHolder)

                FindControl("TitleBar");

                  ph.Controls.Add(theTitleBar);

               }

   }

 

   public class AutoLinks : NameValueCollection

   {

   }

}

Figure 2. The CompanyBasePage class provides a few extra properties (for example, Links) and a predefined and configurable structure made of two tables - PageHeader and TitleBar. Any child class must have these elements, but not necessarily in a fixed position. The base class looks up for a placeholder control with a given name and adds the table as a subobject.

 

The class provides a configurable layout made of two tables, a few graphics, and a link bar. The Links property is declared of type AutoLinks but is actually a simpler version of NameValueCollection. All the elements in the Links collection populate the link bar of the page with frequently accessed URLs. Figure 3 shows the page.


Figure 3. Here is the sample page in action. Notice that the links in the topmost bar are configured programmatically. You can hide both the page header and the title bar if needed. You control the links and the visibility of the tables using custom properties.

 

The page is made of two tables, one above the other. The topmost is called PageHeader; the bottommost is TitleBar. The ShowHeader and ShowTitleBar properties let you control these tables programmatically. See Figure 4 for the source code of the page featured in Figure 3.

 

<%@ Page Language="C#"

   Inherits="AspNetPro.CoreCoder.CompanyBasePage" %>

 

<html>

<title>Index</title>

<script runat="server">

public void Page_Load(object sender, EventArgs e)

{

   Links.Add("Wintellect", "http://www.wintellect.com");

   Links.Add("Vb2-The-Max", "http://www.vb2themax.com");

   Links.Add("asp.netPRO", "http://www.aspnetpro.com");

 }

</script>

 

<body id="body" bgcolor="ivory" style="margin:0">

<asp:placeholder runat="server" id="PageHeader" />

<asp:placeholder runat="server" id="TitleBar" />

 

<form runat="server" id="form">

            <p> Any other content goes here </p>

</form>

</body>

</html>

Figure 4. Here is the source code of the page shown in Figure 3. It is composed of two tables - PageHeader and TitleBar - which are placed one atop the other.

 

Notice the role of the placeholder controls: It is a slick technique that lets you control the exact position of any predefined layout element in child pages. I determined there is no certainty on the order in which the layout of the base and child classes are created, although the order of creation is not standardized and any documentation to prove the contrary is scant.

 

Although mostly credited for providing true separation between code and layout in an ASP page, codebehind in reality is the most effective tool you have to build a hierarchy of pages exploiting the OOP principle of inheritance. If visual inheritance is a feature of Windows Forms applications, codebehind provides you with the opportunity to obtain a similar result with Web forms as well. I described codebehind from a general perspective and used the attributes of the @Page directive to implement the tool. If you use Visual Studio .NET to generate your ASP.NET pages, all you need to do is manually change the base class of the code-behind file generated automatically for each Web page.

The sample code in this article is available for download. Note that the source code includes a code-behind class with a batch file that compiles the class and a sample page that uses the class as well.

Dino Esposito is a trainer and consultant for Wintellect (http://www.wintellect.com) where he manages the ADO.NET and XML classes. Author of Building Web Solutions with ASP.NET and ADO.NET and Applied XML Programming for Microsoft .NET (Microsoft Press), Dino also is a co-founder of http://www.VB2TheMax.com. E-mail him at mailto:[email protected].

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish