RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Design Patterns for ASP.NET Developers, Part 2: Custom Controller Patterns : Page 4

If any part of your ASP.NET applications display pages based on user interaction, browser type, security permissions, or other factors, you'll find these Controller patterns useful.

Implementing the Page Controller Pattern
ASP.NET automatically provides a Presenter implementation for the Model-View-Presenter pattern through a code-behind file for each ASP.NET page. However, you can extend the implementation by adding your own Page Controller in the form of a base class that the code-behind files inherit.

By default, the code-behind class for an ASP.NET page inherits from the Page class in the System.Web.UI namespace. If you create a suitable base class that inherits from Page, you can use this as the base for your own concrete implementations of the code-behind class. This is useful if some or all of your pages require common functionality.

The base class can also perform some of the tasks of a Page Controller by handling the Page_Init or Page_Load events. For example, code in the Page_Load event can select a View to display at runtime for a page, allowing a single page to change its content based on some external condition such as a value in the query string.

By default, the code-behind class for an ASP.NET page inherits from the Page class in the System.Web.UI namespace.
The example application uses a base class named PageControllerBase (in the App_code folder), which inherits from System.Web.UI.Page and exposes three values that the concrete classes that inherit from it can access. These values are a reference to the partial View (a user control) to load and display, the name of the View, and a string value to display when no View is specified:

   // base class for TransferPage2 and TransferPage3
   // implements common tasks and can call method(s)
   // in the concrete page class implementations 
   public class PageControllerBase : Page
      // values that will be available in page class
      protected UserControl displayView = null;
      protected String displayViewName = String.Empty;
      protected String noViewSelectedText = "No View Selected";
The PageControllerBase class handles the Page_Load event to get the name of the View to display from the query string, and then attempts to create an instance of the appropriate user control for the concrete page code to access. At the end of the Page_Load event handler, the code calls a method named PageLoadEvent, passing in the values of the sender and EventArgs originally received as parameters:

   protected void Page_Load(Object sender, System.EventArgs e)
      // get name of view (UserControl) to show in the page 
      displayViewName = Context.Request.QueryString["view"];
      if (displayViewName != null && displayViewName != 
            // load view from ASCX file
            displayView = (UserControl)
               Page.LoadControl(displayViewName + ".ascx");
         catch { }
      // call concrete page class method
      PageLoadEvent(sender, e);
Every page that inherits from this base class must implement the PageLoadEvent method. To ensure that this is the case, the PageControllerBase class declares a virtual method that each concrete page implementation must override:

   // define method that concrete page classes must implement
   // and will be called by this base class after Page_Load
   virtual protected void PageLoadEvent(Object sender, System.EventArgs e)
      // overridden in concrete page implementation
The example application contains two pages, named TransferPage2.aspx and TransferPage3.aspx that inherit from the PageControllerBase class. The code in the overridden PageLoadEvent methods is the same in both pages—it is only the View (the ASPX UI) that differs. However, they could be completely different if required, although all inheriting page should make some use of the common functionality of the PageControllerBase class (or there is no point in inheriting from it!). Here's the PageLoadEvent code used in both pages:

   public partial class TransferPage2 : PageControllerBase
      // override virtual method in PageControllerBase class
      protected override void PageLoadEvent(Object sender, 
         System.EventArgs e)
         // use values that were set in base class Page_Load event
         if (displayView != null)
            pageTitleElement.Text = "Displaying view '" + 
               displayViewName + "'";
            pageHeadingElement.InnerHtml = "Displaying view '" + 
               displayViewName + "'";
            pageHeadingElement.InnerHtml = noViewSelectedText;
         // display actual URL of currently executing page
Figure 7. The CityList View: The figure shows two differing views of the same page.
lblActualPath.Text = Request.CurrentExecutionFilePath; String qs = Request.QueryString.ToString(); if (qs != null && qs != String.Empty) { lblActualPath.Text += '?' + qs; } } }
The preceding code displays the name of the current View in the page title and heading, and adds the user control instance created by the PageControllerBase class to the Controls collection of an ASP.NET Placeholder control declared in the ASPX file:

The final section of the PageLoadEvent method shown above displays the actual page URL so that you can see the effects of the Front Controller implementation (described in the next article in this series). Figure 7 shows the two pages described in this section displaying the "CityList" View.

Author's Note: You can open the page TransferPage2.aspx with the appropriate View displayed by selecting the View name ("CustomerList," "CustomerDetails," or "CityList") in the dropdown list at the bottom of the Default.aspx page. To open the TransferPage3.aspx page with the appropriate View displayed, select "SpecialCustomerList," "SpecialCustomerDetails," or "SpecialCityList." To open the pages with no View displayed, select the page name ("TransferPage2.aspx" or "TransferPage3.aspx") in the dropdown list.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date