Editing a SharePoint Master Page in Visual Studio 2010

I’ll be the first to agree that the best tool for editing a SharePoint master page is SharePoint Designer (SPD).  SPD is able to display both a code and “WYSIWYG” view of the master even if objects on the page are referenced using virtual directories, relative addresses, or addresses that contain dynamic placeholders.  Because Visual Studio can’t open a SharePoint site in place it is unable to provide the same level of editing support. But the problem is that a master page edited in SPD is “customized” and can only be used for that one site (or a single site collection if publishing features have been enabled.) So it has become a best practice to create a custom master in a separate SPD development environment, export it to the file system, and then deploy it in production as an “uncustomized” master page using a feature in a solution. (I documented how to deploy an SPD 2007 master page as a feature in a previous blog here.)

Editing master pages in SPD 2010 continues to be the best practice, but it can be cumbersome for small changes to Enterprise master pages already deployed via a Feature. Sometimes its just not practical to upload the master to a Development site master page gallery, edit it in SPD 2010, and then download the edited copy to be packaged in Visual Studio 2010 and re-deployed to an Enterprise. In those cases it would be nice to make a quick edit in VS 2010. But VS 2010 is unable to interpret the master page in the context of a live site and defaults to the standard code view editor when opening a master page.  This leads to two specific limitations that make even simple edits more difficult.  As you can see from the screen shots below there is no support for expansion/contraction of code sections and Intellisense support is greyed out.

NoExpansion

NoIntellisense

This makes it even more difficult to edit master pages in a code only view. To avoid these limitations you will need to tell VS 2010 which editor to use when opening the master page.  To do this Right-Click on the Master page to be edited in the Solution Explorer and select Open With… from the context menu.  A dialog will open showing all the different Editors that are available.  Highlight the Master Page Editor (Default) entry and click OK to open the Master page using the Master Page Editor in place of the Source Code (Text) Editor.  (Note: Although the Master Page Editor is set as the default just clicking on the master page in Solution Explorer will actually use the Source Code (Text) Editor.  The screenshot below shows the master page after it has been manually loaded into the Master Page Editor using the Open With… menu.  Notice the presence of both Expansion/Contraction Outlining and Intellisense.

MasterPageEditor

A similar problem exists when opening .aspx pages that are not stored in the _Layouts virtual directory.  You can enable full code editing of these pages by using OpenWith… and choosing Web Form Editor (default).

Guest appearance on the GeekSpeak Internet Radio Show

I’ve been invited to do a return guest spot on MSDN’s GeekSpeak Internet radio show August 6, 2008.  The show is broadcast every Wednesday from 12:00-1:00PM Pacific time (3:00-4:00PM Eastern).  I’ll be talking about Branding using master pages in SharePoint.  The abstract for the talk and registration link are listed below.

Making SharePoint not look like SharePoint – SharePoint’s use of ASP.NET master pages makes it possible to completely change the branding of your SharePoint site to match your existing corporate branding.  In this geekSpeak, Paul Stork will demonstrate how to convert a sample web page from an existing corporate Web site into a master page for SharePoint.  The new master page will then be applied to a SharePoint site completely changing the look and feel to match the existing web page.  Join us to see how SharePoint’s use of master pages can make branding your SharePoint site possible.

 

Register here:

http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032383094&Culture=en-US

 

Branding Talk for the Cleveland SharePoint User Group

I will be speaking at the Cleveland SharePoint User Group on Wednesday, July 23rd.  The meeting will start at 4:00pm.  My topic will be "SharePoint Branding”.  Here’s a brief description of the talk:

SharePoint Branding
SharePoint’s use of ASP.NET master pages makes it possible to completely change the branding of your SharePoint site.  In this talk I will describe how SharePoint uses master pages.  I’ll also demonstrate building a new master page from scratch and converting an existing HTML page’s look and feel to SharePoint.  Join us to see how SharePoint’s use of master pages can make branding your SharePoint site possible

The location for the July 23rd event has changed due to construction in the Cleveland Microsoft Office Conference Room.  Instead of meeting at the Microsoft Office we will be at the Oxford & Associates office.  Address information for the office is below:

Oxford & Associates

Commerce Park 4

23240 Chagrin Boulevard Suite 130

Beachwood, OH  44122

Wednesday, July 23rd from 4pm – 6:30pm

Feature to Install a Custom Master Page

A former student brought an excellent BLOG post that Heather Solomon made last October (http://www.heathersolomon.com/blog/articles/servermstpageforsitecollect_feature.aspx) to my attention recently.  Heather demonstrated how to create a Feature that could be used to install a Custom Master Page for a Site Collection.  There was however one limitation to the approach that Heather used, it could only be used on a Site where the Publishing Feature was enabled.  My student wondered if there was a way to do something similar for regular WSS Team Sites.

Normally, I teach students how to do this by planning ahead and creating or modifying Site Definitions BEFORE you create the Site Collection and Top Level Site.    The MasterUrl and CustomMasterUrl attributes represent two replaceable parameters that can be used to set the Masterpage attribute of the @Page declaration on the pages of a SharePoint site.  “Out of the Box“ .aspx pages point to a Masterpage at ~/masterurl/default.master. This will be replaced at runtime by the MasterUrl property of the Website.  The default setting for this is _catalogs/masterpage/default.master.  This is the default.master file in the Master Pages gallery of the website.  Until you edit this file using SharePoint Designer it will point to a ghosted copy of the file in the TEMPLATE\GLOBAL directory of the 12 hive.  You can also ghost custom .Master files from your Site Definition directory into the Masterpage gallery of the site using a Module Element.  Then you can set the MasterUrl and/or CustomMasterUrl attributes of the Configuration Element in the ONET.xml file to point at these ghosted .Master files.  If you also change the @Page directive of the .aspx files on your site to use ~/masterurl/custom.master you will establish a hierarchy of master pages that will be used.  The page will first try to use the customMasterUrl setting, then the masterUrl setting, and finally the default.master file in GLOBAL.

Making these changes later will NOT result in a change to existing Sites, but you can also set the MasterUrl and CustomMasterUrl properties of a Website programmatically.  So I reasoned it would be possible to create an Event Handler that would fire when a Feature was activated to set these properties and then move the .Master files using a Feature Module.  Activating this Feature on a site would accomplish the same changes outlined above by a custom site definition.  Here’s how it can be done.

First, we need a Feature. To create our Feature we need a Subdirectory Called CustomMaster in the TEMPLATE\FEATURES directory of the 12 hive.  Then we need add 4 files to this directory:  Feature.xml, Elements.xml, Custom.master, and myDefault.master.

FEATURE.XML This file is used to identify the feature and list out the items that will be part of the Feature.  Our Feature will include an assembly that will contain code to run in response to Feature events and an Elements.xml file.  The code for our Feature is listed below:

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <Feature xmlns="http://schemas.microsoft.com/sharepoint/"
   3:           Id="90969656-A1C9-4f40-A95F-A3BDDF5723BF"
   4:           Title="Use Custom Master File"
   5:           Scope="Web"
   6:           ReceiverAssembly="CustomMaster, Version=1.0.0.0,
   7:               Culture=neutral, PublicKeyToken=bcee0f83b26fbb16"
   8:           ReceiverClass ="CustomMaster.ChangeMaster" >
   9:      <ElementManifests>
  10:          <ElementManifest Location="Elements.xml"/>
  11:      </ElementManifests>
  12:  </Feature>

ELEMENTS.XML – In this file we will identify two .Master files that will be ghosted to the masterpages gallery of the site.

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:      <Module Name="AddMasters" Url="_catalogs/MasterPage" >
   4:          <File Url="MyDefault.master" Type="GhostableInLibrary"
   5:            IgnoreIfAlreadyExists="True">
   6:            <Property Name=“ContentType
   7:               Value=“$Resources:cmscore,contenttype_masterpage_name;" />
   8:          </File>
   9:          <File Url="custom.master" Type="GhostableInLibrary" 
  10:            IgnoreIfAlreadyExists="True">
  11:            <Property Name=“ContentType
  12:               Value=“$Resources:cmscore,contenttype_masterpage_name;" />
  13:          </File>
  14:    </Module>
  15:  </Elements>

MYDEFAULT.MASTER and CUSTOM.MASTER – These are copies of the default.master file from the TEMPLATE\GLOBAL directory of the 12 hive.  If your .aspx page references the master file ~/masterUrl/default.master then myDefault.master will be used.  If you reference ~/masterUrl/custom.master then Custom.Master will be used.  WARNING: Do not use SharePoint Designer to edit files stored in the 12 hive.  This would break the files.

The last piece of the Feature is a Feature event handler that will be used to modify the masterUrl and customMasterUrl properties of the Website programmatically.  The event handler will set the properties when the Feature is activated and reset them to the default when the Feature is deactivated.  The code for the event handler is listed below:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Text;
   4:  using Microsoft.SharePoint;
   5:   
   6:  namespace CustomMaster
   7:  {
   8:      public class ChangeMaster:Microsoft.SharePoint.SPFeatureReceiver 
   9:      {
  10:          public override void FeatureInstalled
  11:            (SPFeatureReceiverProperties properties)
  12:          {
  13:          }
  14:          public override void FeatureUninstalling
  15:             (SPFeatureReceiverProperties properties)
  16:          {
  17:          }
  18:          public override void FeatureActivated
  19:             (SPFeatureReceiverProperties properties)
  20:          {
  21:              SPWeb CurrentWeb = properties.Feature.Parent as SPWeb;
  22:              CurrentWeb.MasterUrl = "/_catalogs/masterpage/MyDefault.master";
  23:              CurrentWeb.CustomMasterUrl = "/_catalogs/masterpage/custom.master";
  24:              CurrentWeb.Update();
  25:          }
  26:          public override void FeatureDeactivating
  27:             (SPFeatureReceiverProperties properties)
  28:          {
  29:              SPWeb CurrentWeb = properties.Feature.Parent as SPWeb;
  30:              CurrentWeb.MasterUrl = "/_catalogs/masterpage/default.master";
  31:              CurrentWeb.CustomMasterUrl = "/_catalogs/masterpage/default.master";
  32:              CurrentWeb.Update();
  33:         }
  34:      }
  35:  }
  36:   

Once the event handler has been compiled and added to the Global Assembly Cache and the Feature directory has been created you can Install and Activate the Feature.  To install the Feature use the following command line:

stsadm -o installfeature -n CustomMaster

Then you can go to the Site Features link in SiteSettings on any SharePoint website and activate the Feature.  Every website where the Feature is activated will use the myDefault.master stored in the Feature as its .master file.  If you modify the @Page declaration of a page on the site to use ~/masterUrl/Custom.master then the Custom.master will be used.

*** Updated July 3, 2008 ***

I noticed recently that I left one line out of the Elements.xml file which prevented the feature from working in Site Collections where Publishing was turned on.  In those sites the master pages gallery contains two content types so you have to specify what type of file you are "ghosting" with your .  The Code that was added is italized in the code listing above.