MasterPages: Improved VersionPaul Wilson
OverviewMasterPages is the most flexible and easiest to use of Page Template solutions, and since it was created by Microsoft it will likely someday be in ASP.NET itself. However, the original demo lacks designer support, suffers from poor performance, and is NamingContainer "happy", giving IDs like Container:_ctl0:Region:Control. This article demos an improved version of MasterPages that has designer support, better performance without the flexible but annoying NamingContainer "problem", and adds the ability to define a default content region and default template file.
Creating a TemplateTo create a MasterPages Template you start by creating an ASP.NET User Control and then add your common page layout that you intend all of your pages share. Then you mark any spots in the layout that will be defined in individual pages with a "ContentRegion" control, along with a unique ID to be matched later. You can include multiple ContentRegions, and you can add default content inside ContentRegions that will be used for pages that do not contain a matching ID. Note the Register directive and control syntax is automatic with drag-n-drop.
Listing 1: Creating a Template
<%@ Control %> <%@ Register TagPrefix="Wilson" Assembly="WilsonMasterPages" Namespace="Wilson.MasterPages" %> <html> <head> <title>MasterPages</title> </head> <body> <h1><wilson:contentregion id="MPHeader" runat="server"> Page Header</wilson:contentregion></h1> <form id="frmMain" method="post" runat="server"> <wilson:contentregion id="MPContent" runat="server"> Default Content</wilson:contentregion> </form> <h2><wilson:contentregion id="MPFooter" runat="server"> Page Footer</wilson:contentregion></h2> </body> </html>
Defining the DefaultsYou can define two MasterPages default settings in your app's web.config file. The Wilson.MasterPages.TemplateFile app-setting is used to specify the default User Control that will be used for all MasterPages Templates when not specified. The Wilson.MasterPages.DefaultContent app-setting is used to specify the default ContentRegion ID so you can add its content directly to the MasterPage control. The concept of a default ContentRegion is not likely to be added by Microsoft, and its use is optional even here, but I personally find it a useful concept.
Listing 2: Defining the Defaults
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="Wilson.MasterPages.TemplateFile" value="~/Template.ascx" /> <add key="Wilson.MasterPages.DefaultContent" value="MPContent" /> </appSettings> <system.web> <!-- Normal web.config settings go here --> </system.web> </configuration>
Using the TemplateTo use the MasterPage Template you start by creating an empty ASP.NET Page, stripping out all the standard content that the wizard automatically adds. Then you add a "MasterPage" control, possibly with a TemplateFile attribute. Next, directly add the content of the default ContentRegion to the MasterPage. Finally, add other "ContentRegion" controls to the MasterPage, being careful to match up their IDs with the IDs that were specified in the Template itself, skipping any ContentRegions that you prefer to accept their default content.
Listing 3: Using the Template
<%@ Page %> <%@ Register TagPrefix="Wilson" Assembly="WilsonMasterPages" Namespace="Wilson.MasterPages" %> <wilson:masterpage runat="server" masterpagefile="Template.ascx"> <wilson:contentregion id="MPHeader" runat="server"> Sample Page</wilson:contentregion> Real Content for the Default ContentRegion </wilson:masterpage>
Source Code NotesThe original MasterPages demo had both ContentContainer and Region controls inherit from PlaceHolder and INamingContainer, with Content inheriting Panel. However, PlaceHolders are not intended for designer support, only run-time, so my MasterPage inherits from HtmlContainerControl, with a ReadWrite Designer. I combined the Content and Region controls into a single ContentRegion control, which inherits from Panel, and I added a "WhiteSmoke" background color to it. I also removed the begin and end "div" tags and the INamingContainer interface.
ConclusionThis custom version of Microsoft's MasterPages demo Page Templating controls now has design-time support and performs faster, and adds a few default settings. There is still no "visual" inheritance; that requires built-in support in VS.NET. It should be noted that the removal of the NamingContainers is making it faster and avoiding the annoying hierarchical control names, but this comes at a loss of some flexibility -- no guaranteed unique names and no repeating templates. Finally see my website for a demo of making the templates user-selectable as well.
Author BioPaul Wilson is a software architect in Atlanta, currently with a medical device company. He specializes in Microsoft technologies, including .NET, C#, ASP, SQL, COM+, and VB. His WilsonWebForm Control allows Multiple Forms and Non-PostBack Forms in ASP.NET. He is a Microsoft MVP in ASP.NET and is also recognized as an ASPFriend's ASPAce/ASPElite. He is a moderator on Microsoft's ASP.NET Forums, as well as one of the top posters. He is certified in .NET (MCAD), as well as also holding the MCSD, MCDBA, and MCSE. Please visit his website, www.WilsonDotNet.com, or email him at Paul@WilsonDotNet.com.