Master Pages


One of the most tedious aspects of customizing and branding sites in WSS 2.0 has to do with creating a consistent look and feel across pages. The root of this problem is caused by the fact that ASP.NET 1.1 does not provide an effective page-templating technique that can be used to define a common layout across the pages within a WSS 2.0 site. As a result, many developers and designers working with WSS 2.0 and Microsoft SharePoint Portal Server 2003 have resorted to copying and pasting HTML layouts from page to page. As you can imagine, this makes it very hard to customize and maintain sites whose layout requirements differ from the out-of-the-box experience you get with a standard WSS 2.0 site.

When master pages were introduced with ASP.NET 2.0, they were embraced by developers because they provide a more elegant way to define the common layout for all pages within a site. The fact that WSS 3.0 was designed from the ground up around the concept of master pages is a very welcome change for those with experience branding sites with the previous version of WSS.

The last chapter reviewed the basic ASP.NET architecture for master pages. A master page is a template that allows you to define a standard page layout for an entire site with common elements, such as a banner and navigation controls. The pages that link to a master page are known as content pages. The key concept is that each content page that links to a master page benefits from the shared layout and then can extend that master page by using replaceable named placeholders to add unique content.

In this book, you have already seen several places where master pages have been used. In the previous chapter, you saw that the majority of standard WSS application pages link to a master page in the virtual _layouts directory named application.master. You have also seen that you can link to application.master when creating your own custom application pages.

In this chapter, you have seen how to create page templates for site pages that link to the standard master page named default.master. This makes it very simple to create site pages that have the same look and feel as the standard site pages that are provided out of the box with WSS.

As you begin to think through the bigger picture with respect to branding WSS sites with master pages, there is one critical factor to keep in mind. Site pages and application pages use separate master pages. In this chapter, we will examine how to provision and use a custom master page for the site pages within a site. This technique allows you to change the layout for every site page within any site to which you want to apply your own custom branding. However, the technique being covered in the next section cannot be applied to application pages because the majority of standard WSS application pages rely on a single master page named application.master that cannot be replaced or customized on a site-by-site basis.

Understanding default.master

Every WSS 3.0 site is provisioned with a special catalog known as the Master Page gallery containing a master page template named default.master. This standard master page is deployed during the standard WSS installation on the file system of the front-end Web server at the following path (there is a line break in the file path to make it more readable).

 C:\Program Files\Common Files\Microsoft Shared       \web server extensions\12\TEMPLATE\GLOBAL\default.master

Whenever you create a new site, WSS provides provisioning instructions to create the Master Page gallery and provision an instance of default.master within the site by using a standard site-relative path.

 /_catalogs/masterpage/default.master

The default.master page is widely used in WSS. It defines a common layout for every site’s home page (default.aspx) as well as all of the standard WSS form pages associated with lists and document libraries (e.g., AllItems.aspx or NewItem.aspx). The default.master page can also serve as the master page for your custom site pages, as has been demonstrated in all of the page templates used in the CustomSitePages project.

To understand the best practice for creating site pages that link to default.master, it’s important that you have a basic understanding of what’s defined inside this file. It’s definitely worth your time to open up a copy of the default.master file within Visual Studio and try to absorb all that’s there. While it might take some time to get to know everything inside, it’s a worthwhile investment for any developer serious about mastering WSS development.

The default.master page contains the basic layout for a site page including elements such as HTML, HEAD, BODY, and FORM. Within these standard HTML elements, you will find three important types of components:

  • Controls for links, menus, icons, and navigation components

  • Named placeholders

  • Delegate controls

Many server-side controls that are used to construct the default.master page template represent encapsulated logic and user interface components that are compiled into the Microsoft.SharePoint assembly. Examples of these controls include the SPWebPartManager object and controls to provide navigation components, such as breadcrumb trails and menus for navigating around the site.

Named placeholders provide an extensibility mechanism used to add unique content to a page template or page instance that is linked to a master page. Delegate controls provide an elegant way to substitute elements into the layout of default.master that affects every site page that links to it. The following fragment of HTML is extracted from default.master and is simplified to demonstrate how each of these component types is used.

 <%@Master language="C#"%> <%@ Register Tagprefix="SharePoint"     Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, …" %> <HTML runat="server"> <HEAD runat="server">     <!-- SharePoint Utility Controls -->     <SharePoint:CssLink  runat="server"/>     <SharePoint:Theme  runat="server"/>     <!-- Named Placeholders -->     <Title ID=onetidTitle>       <asp:ContentPlaceHolder id=PlaceHolderPageTitle runat="server"/>     </Title>     <asp:ContentPlaceHolder                              runat="server"/>     <!-- Named Delegate Control -->     <SharePoint:DelegateControl  runat="server"                                Control                                AllowMultipleControls="true"/> </HEAD>

The HEAD element of default.master shows the use of standard WSS server-side controls, such as CssLink and Theme. These controls contain the encapsulated logic to integrate the standard Cascading Style Sheet (CSS) files used by WSS and supply the support required for user-applied themes. Note that these same two controls are also present inside application.master so that the standard CSS files and themes continue to work as users navigate to application pages.

You can also see that the HEAD element defines two named placeholders with an ID of PlaceHolderPageTitle and PlaceHolderAdditionalPageHead. The placeholder named PlaceHolderPageTitle makes it possible to substitute the page title when creating a page template or customizing a site page instance. The placeholder named PlaceHolderAdditionalPageHead makes it possible to add items such as extra meta tags into the HEAD section. The following example displays a page template that substitutes these two placeholders with unique content.

  <%@ Page MasterPageFile="~masterurl/default.master" %> <asp:Content  runat="server"              ContentPlaceHolder>   My Custom Page Title </asp:Content> <asp:Content  runat="server"              ContentPlaceHolder>   <META name="keywords" content="Software, Consulting, Money, Fame" /> </asp:Content> 

WSS Navigation Components

Several standard controls are included with default.master that provide the basic infrastructure for navigation. For example, the ASP.NET SiteMapPath control that has been positioned at the very top of the page populates a breadcrumb navigation menu that allows users to navigate from the current site upward to the parent site and all the way to the top-level site of the current site collection.

Navigation in WSS is based on the navigation-provider infrastructure introduced in ASP.NET 2.0. In this model, a navigation provider is designed and created to provide a set of navigation nodes. In many cases, the nodes supplied by a navigation provider can be bound to a menu control or a treeview to give users a user interface component with which to navigate around the site.

WSS provides several standard navigation providers such as the SPNavigationProvider, SPSiteMapProvider, SPContentMapProvider, and SPXmlContentMapProvider classes. You can see where all the active navigation providers are defined by examining the siteMap section inside the system.web section of the standard WSS web.config file.

The top link bar and the Quick Launch menu represent the two main navigation components defined in default.master. The top link bar is defined by using a WSS-specific control of type AspMenu along with a SiteMapDataSource control that is configured to point to the standard SPNavigationProvider component. The Quick Launch menu is defined in the same way. The major difference between the two is that the SiteMapDataSource for the top link bar is configured with a StartingNodeUrl attribute with a value of sid:1002, whereas the Quick Launch menu is configured with a StartingNodeUrl attribute with a value of sid:1025.

The next question you should be asking is what the significance is between 1002 and 1025. It has to do with the data stored in the content database for tracking navigation nodes. The top node for the top link bar has an ID of 1002, and the top node to the Quick Launch menu has an ID of 1025.

WSS provides users with the flexibility to add navigation nodes to either the top link bar or the Quick Launch menu. You can access the application pages that allow users to perform these actions from the Site Settings page. What’s nice about this scheme for developers is that you can customize the standard WSS navigation menus without making any changes to default.master. You simply need to find a way to add new navigation nodes to the content database.

While it’s possible for users to add navigation nodes through site administration pages in the browser-based user interface, it’s also possible and far more flexible to accomplish the same goal by using the WSS object model. The CustomSitePages feature provides code in the FeatureActivated event handler to add navigation nodes to construct a custom drop-down menu in a fashion that is not possible to replicate through the user interface. Examine the following code and observe how it creates SPNavigationNode objects and adds them to the collection of nodes that define the structure for the top link bar.

 public override void FeatureActivated(SPFeatureReceiverProperties properties) {   // get a hold of current site in context of feature activation   SPWeb site = (SPWeb)properties.Feature.Parent;   SPNavigationNodeCollection topNav = site.Navigation.TopNavigationBar;   // create dropdown menu for custom site pages   SPNavigationNode DropDownMenu1;   DropDownMenu1 = new SPNavigationNode("Site Pages", "", false);   topNav[0].Children.AddAsLast(DropDownMenu1);   // add navigation nodes to create menu items   DropDownMenu1.Children.AddAsLast(       new SPNavigationNode( "Site Page 1",                             "SitePages/Page01.aspx"));   DropDownMenu1.Children.AddAsLast(       new SPNavigationNode("Site Page 2",                             "SitePages/Page02.aspx")); }

Delegate Controls

WSS introduces a powerful new extensibility mechanism known as delegate controls. In some ways, a delegate control is similar to a named placeholder because it defines a region inside a master page that can be substituted with unique content to meet the needs of a particular business solution. Like a placeholder, a delegate control can optionally supply default content that is used until a substitution is performed.

One major difference when compared to placeholders is that the substitution mechanism for replacing the contents of a delegate control is driven through feature activation. Therefore, you can replace what’s defined inside a delegate control in default.master without requiring any changes to default.master or the site pages that link to it. All you need to do is define a Control element within a feature and then activate that feature.

A significant aspect of using delegate controls involves the scope of the feature that is being used to drive substitution. When you design a feature to substitute the contents of a delegate control, your feature can be scoped at any of the four supported levels. These levels include site scope, site collection scope, Web application scope, and farm scope. This dimension of delegate controls provides a powerful mechanism for enabling and disabling functionality on a wide-scale basis.

Let’s begin by looking at an example of a delegate control that is defined in default.master to create the region that defines the standard search area in site pages just above the Site Settings menu. The delegate control definition in default.master looks like the following:

 <SharePoint:DelegateControl      runat="server"   Control />

This is an example of a delegate control that defines no default content. Instead, the default content for this delegate control is supplied by a standard WSS feature named ContentLightup. The ContentLightup feature defines a Control element that substitutes content into the SmallSearchInputBox delegate control by referencing a built-in user control with the standard WSS search area content.

 <Control      Sequence="100"   Controlsrc="/books/4/221/1/html/2/~/_controltemplates/searcharea.ascx" />

Assume that you want to get rid of the standard search area content and replace it with your own custom content for a particular business solution. That’s what delegate controls were designed for. If you want to follow along with the sample code that accompanies this chapter, you should open the Visual Studio project named CustomBranding. This project contains the definition for a feature named CustomBranding that is scoped to the level of a site collection.

If you want to replace a delegate control, such as the WSS search area, with your own customized version, you start by adding a Control element to a feature. The Control element should have an ID value of SmallSearchInputBox. The Control element should also have a Sequence number smaller than any other active Control element pointing to the same ID. The following code demonstrates how the Control element is defined inside the elements.xml file of the CustomBranding feature.

 <Control      Sequence="10"   Controlsrc="/books/4/221/1/html/2/~/_controltemplates/Litware/LitwareSearchArea.ascx" />

Note that this Control element has a sequence number of 10, which is smaller than the Control element defined in ContentLightup with a Sequence number of 100. Once the CustomBranding feature is activated within a site collection, all of the site pages that link to default.master replace the standard WSS search area with whatever content you have defined inside the custom user control named LitwareSearchArea.ascx. The following code defines a starting point for creating a custom user control that supplies custom search behavior.

  <%@ Control Language="C#" %> <script runat="server">     protected void cmdRunSearch_Click(object sender, EventArgs e) {       // LEFT AS AN EXERCISE FOR THE READER       // Step 1: add code here to perform custom search       // Step 2: redirect user to custom search results page     } </script> <table>   <tr>     <td>       <asp:Button  runat="server" Text="Search"                   OnClick="cmdRunSearch_Click" />     </td>     <td>       <asp:TextBox  runat="server" Width="120" />     </td>   </tr> </table> 

While the CustomBranding feature is designed to activate at the level of a site collection, remember that delegate controls can be substituted at any scope supported by features. You can add the Control element that substitutes the delegate control named SmallSearchInputBox to a feature scoped at the Web application or farm level to replace the standard WSS search area on a larger scale.

If you have plans to replace the WSS search area by using a Control element, it’s important for you to understand that Microsoft Office SharePoint Server (MOSS) uses the same approach. The Standard Edition of MOSS provides a feature that replaces the SmallSearchInputBox delegate control by using a Control element with a sequence number of 50. The Enterprise Edition of MOSS provides a feature that replaces the SmallSearchInputBox delegate control by using a Control element with a sequence number of 25.

The main point here is that you obtain a more enhanced version of the search area as you upgrade from WSS to MOSS Standard Edition and then to MOSS Enterprise Edition. You should assign the sequence number for your Control element accordingly depending on whether you want to override the enhanced versions of the search area supplied by MOSS.

In addition to substituting delegate controls by using .ascx files, WSS also supports delegate control substitution by using control classes that are compiled into assemblies installed in the Global Assembly Cache. As an example, let’s examine a technique for replacing the SiteMapDataSource that is used to populate the Quick Launch menu. Examine the following fragment from the standard default.master page template that defines a delegate control named QuickLaunchDataSource.

 <SharePoint:DelegateControl       runat="server"      Control>   <Template_Controls>     <asp:SiteMapDataSource       SiteMapProvider="SPNavigationProvider"       ShowStartingNode="False"              StartingNodeUrl="sid:1025"       runat="server" />   </Template_Controls> </SharePoint:DelegateControl>

Unlike the last example of a delegate control, this delegate control with a ControlId of QuickLaunchDataSource defines default content that is used until a substitution is performed. The default content includes a SiteMapDataSource control with an ID of QuickLaunchSiteMap. If you want to substitute this control with a different SiteMapDataSource control, you can add the following Control element to a custom feature.

 <Control   Sequence="1"  ControlAssembly="System.Web, ..."  Control>   <Property Name="ID">QuickLaunchSiteMap</Property>   <Property Name="SiteMapProvider">SPSiteMapProvider</Property>   <Property Name="ShowStartingNode">False</Property> </Control>

As shown in the previous example, this Control element provides an ID that matches the ControlId of the target delegate on which the substitution should be performed. However, this example differs because it uses the ControlAssembly and ControlClass attributes to reference a specific control type within a target assembly.

You should also observe that the Control element contains several nested Property elements that define the initialization parameters for the control instance being used in the substitution. It is important in this example that the control instance being created is assigned an ID of QuickLaunchSiteMap because the hosting page expects to find a control of that name. The control instance is also initialized to use the SPSiteMapProvider class, which provides different behavior than the default that uses the SPNavigationProvider class instead.

Customizing default.master

The previous section of this chapter demonstrated several branding techniques involving placeholder and delegate controls that did not require making any changes to default.master. However, many developers and end users alike will come to the conclusion that they want to make changes to default.master. This is something that the SharePoint Designer makes very easy to accomplish. You can simply open default.master and make whatever changes you want. The SharePoint Designer makes it possible to work in either Code view or Design view when you are customizing a master page such as default.master.

From an architectural standpoint, it’s important to acknowledge that the default.master page follows the same rules for ghosting and unghosting as the site pages that link to it. When a site is initially created, default.master is uncustomized. When site pages that link to default.master are requested, the master page template is loaded from the file system of the front-end Web server and processed like any other ghosted page. However, default.master becomes unghosted once a user customizes it with the SharePoint Designer. These customization changes are stored inside the content database just like customizations to site pages, such as default.aspx. From that point on, default.master is processed like any other customized page and must follow all of the rules of safe mode processing.

Note that it’s possible to customize the master page for a site while leaving the site pages that link to it uncustomized. Likewise, it’s possible to customize one or more site pages while leaving their underlying master page uncustomized. Furthermore, if you customize either the master page or site pages and later wish to undo your changes, both the browser-based UI of WSS and the SharePoint Designer provide simple menu commands to discard customization changes from the content database and revert back to the original page template.

Even though customizing a master page with the SharePoint Designer provides a quick and easy way to make changes, it’s difficult to track these changes in a source code management system. It’s also difficult to make such customization changes repeatable across site collections in a large-scale deployment. Instead of using this type of customization strategy, a better approach for a developer is to create a page template for a custom master page. This topic is covered in the next section of this chapter.

Creating a Custom Master Page Template

Creating a custom master page template involves several steps. First, you must create the master page template itself. Second, you must create a custom feature that provisions an instance of this master page template inside the Master Page gallery for a specific site. Finally, you need to add some code to redirect site pages to use your custom master page instead of using default.master. The Visual Studio project named CustomBranding provides a working sample that demonstrates how all of the pieces fit together.

Remember that the CustomBranding feature is scoped to the level of the site collection. While you can create a custom feature scoped at the site level to integrate a custom master page template, it’s better to design such a feature at the site collection level because users typically want branding to occur at this level. It is less convenient if you force users to activate the feature separately for every site within a site collection.

You can create a custom template by using two different approaches. First, you can make a copy of default.master and then modify it according to taste. A second approach involves starting from scratch so that you can design the exact HTML layout you’re looking for. If you start from scratch, be sure to think through which named placeholders you need to include. There are over 30 named placeholders defined inside default.master, and many of the standard site pages, such as default.aspx and AllItems.aspx, assume that whatever master page they link to will have these same named placeholders.

If you forget to include the same set of named placeholders found in default.master, you will likely experience problems. ASP.NET generates errors whenever it finds that a site page references a named placeholder that is not defined in the master page to which it is linked.

The custom master page template used in the CustomBranding project is named Litware.master. The Litware.master template is a variation on the default.master template with changes to allow for fly-out menus on both the top link bar and Quick Launch menu. The CustomBranding feature includes a Module element that has been designed to provision an instance of the Litware.master page template into the Master Page gallery of the top-level site.

  <Module Name="MasterPages" List="116" Url="_catalogs/masterpage">   <File Url="Litware.master" Type="GhostableInLibrary" /> </Module> 

Note that this Module element has several differences compared with the Module element for provisioning site pages shown earlier in this chapter. While the previous Module was used to provision pages into a site, it did not target a document library. However, this Module targets the Master Page gallery, which is a special type of document library. Therefore, the Module is defined with a List attribute of 116, which is the list type identifier for the Master Page gallery. The Url attribute for this Module is defined with a value of _catalogs/masterpage, which is the standard site-relative path to the Master Page gallery.

If you examine the File element that provisions an instance of Litware.master, you notice that the Type attribute has a value of GhostableInLibrary as opposed to a value of Ghostable that was shown earlier when provisioning site pages inside a site but outside the scope of a document library. A value of GhostableInLibrary should be used whenever you are provisioning an instance of a file, such as a master page template, inside a target document library.

We have reviewed the steps involved in creating a master page template and provisioning an instance of it in the Master Page gallery of the top-level site. The next step involves redirecting all site pages within a site to link to this provisioned instance of our custom master page template. To understand the technique for accomplishing this, take a closer look at the MasterPageFile attribute defined within a Page directive. Examine the following page template, which is defined to link to a target master page by using a special syntax in the form of~masterurl/default.master.

  <%@ Page MasterPageFile="~masterurl/default.master" %> <asp:Content ContentPlaceHolder runat="server">   Custom content goes here </asp:Content> 

The value of~masterurl/default.master represents a tokenized reference to a master page that can be changed programmatically on a site-wide basis. The support for tokenized master page references is provided by the SPVirtualPathProvider class. The way things work is that the SPVirtualPathProvider class reads the value of an SPWeb property named MasterUrl at run time and then parses this value into the MasterPageFile attribute of an .aspx file before sending it to the ASP.NET page parser. You can redirect any site page that uses this token by acquiring an SPWeb reference to the current site and then updating the MasterUrl property.

  SPWeb site = SPContext.Current.Web; string MasterUrlPath = site.ServerRelativeUrl; if (!MasterUrlPath.EndsWith(@"/"))   MasterUrlPath += @"/"; MasterUrlPath += @"_catalogs/masterpage/Litware.master"; site.MasterUrl = MasterUrlPath; site.Update(); 

From this code, you can see that a MasterUrl property value should be parsed together using the ServerRelativeUrl property. You should also note that the ServerRelativeUrl property ends with a forward slash in some sites, but not all sites. Therefore, you should add conditional logic to append the forward slash onto the end of the ServerRelativeUrl property if it is not already there. Next, you should append a site-relative path to the master page instance where it exists inside the Master Page gallery. Once you parse together the complete serverrelative path to the master page instance, you can assign that value to the MasterUrl property of the current SPWeb object and call the Update method to save your changes.

It’s important to remember that the Master Page gallery is scoped at the site level and not the site collection level. Do not be confused into thinking that all sites inside a site collection automatically use the same master page instance. Each site has its own Master Page gallery with its own default.master instance as well as its own MasterUrl property. You must supply additional code if you want all child sites within a site collection to synchronize on a single master page instance in the Master Page gallery of the top-level site. With the use of recursion, it’s not too difficult to write the code against the WSS object model to accomplish this task.

The CustomBranding project provides a custom application page named CustomBrand.aspx that provides code to redirect all site pages within a site collection to link to the instance of litware.master that is provisioned in the Master Page gallery of the top-level site. Once you activate the CustomBranding feature, you can navigate to the application page named CustomBrand.aspx by using a custom menu item that is added to the Site Settings menu. This application page provides a command button that allows the user to execute the following code.

  protected void cmdApplyCustomBrand_Click(object sender, EventArgs e) {   SPWeb site = SPContext.Current.Site.RootWeb   string MasterUrlPath = site.ServerRelativeUrl;   if (!MasterUrlPath.EndsWith(@"/"))     MasterUrlPath += @"/";   MasterUrlPath += @"_catalogs/masterpage/Litware.master";   ApplyCustomBrand(MasterUrlPath, site); } protected void ApplyCustomBrand(string MasterUrlPath, SPWeb site) {   site.MasterUrl = MasterUrlPath;   site.Update();   // use recusion to update all child sites in site collection   foreach (SPWeb child in site.Webs) {     ApplyCustomBrand(MasterUrlPath, child);   } } 

The code in the event handler named cmdApplyCustomBrand_Click begins by parsing together the server-relative path to the instance of Litware.master in the Master Page gallery of the top-level site. The event handler then calls a method named ApplyCustomBrand to update the MasterUrl of the top-level site.

However, the ApplyCustomBrand method has also been written to enumerate through all child sites below the top-level site and recursively call itself to update them. This recursion continues to crawl the hierarchy of child sites until the MasterUrl property of every site within the site collection is updated to redirect all site pages so that they link to the instance of litware.master that is provisioned in the Master Page gallery of the top-level site.

This technique provides a quick and easy approach to redirect all site pages within a site collection to a custom master page. It works well because all standard WSS site pages, such as default.aspx and AllItems.aspx, are all defined by using the dynamic token ~masterurl/default.master. You can follow suit by defining site page templates using the same technique demonstrated in this chapter.

In addition to~masterurl/default.master, there is another dynamic token for master pages in the form of~masterurl/custom.master. This dynamic token works in conjunction with the CustomMasterUrl property of a site and provides a secondary target master page that can be switched out programmatically. This allows you to create designs in which you can switch the master page used by your custom page templates while leaving the standard WSS pages alone so they continue to link to default.master.

In addition to the two dynamic tokens presented in this chapter, WSS also supports two static master page tokens that start with either~site or~sitecollection. These static tokens allow you to hardcode a relative path to a master page from the root of either the current site or the current site collection. This allows you to create site page templates that point to a specific custom master page instance without requiring any code to perform redirection.




Inside Microsoft Windows Sharepoint Services Version 3
Inside Microsoft Windows Sharepoint Services Version 3
ISBN: 735623201
EAN: N/A
Year: 2007
Pages: 92

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net