“Mastering” branding of SharePoint

16. April 2009

Ok, I am exaggerating here. This post will not be about “mastering” the branding but rather about branding through master pages. This post is another post in a series of posts where I try to learn SharePoint. When I found out that SharePoint is based on ASP.NET master pages I immediately thought it would be fun to create a SharePoint that would look exactly like my web pages. So, here is my target visual.

   SP_Master1_Target

 

Creating new master page

By looking at the default.master page (located at C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\GLOBAL\default.master) I got scared. This page is not simple, let me say it this way. I tried to come up with a clean minimal page. I found a minimal master page on MSDN. Unfortunately that page didn’t work and I had no clue why (I guess it’s because I don’t have MOSS but just WSS installed on my machine). I then tried to come up with my own minimal master page. Here is the result.

 

<%@Master language="C#"%>
<%@ Import Namespace="Microsoft.SharePoint" %> 
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" 
  Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" 
  Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" 
  Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="wssuc" TagName="Welcome" src="~/_controltemplates/Welcome.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="DesignModeConsole" 
  src="~/_controltemplates/DesignModeConsole.ascx" %>

<html id="HTML1" dir="<%$Resources:wss,multipages_direction_dir_value%>" runat="server" 
  xmlns:o="urn:schemas-microsoft-com:office:office">

<head id="HEAD1" runat="server">
    <META Name="progid" Content="SharePoint.WebPartPage.Document">
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    <META HTTP-EQUIV="Expires" content="0">
    <SharePoint:RobotsMetaTag ID="RobotsMetaTag1" runat="server"/>
    
    <Title ID="onetidTitle">
        <asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>
    </Title>
    
    <SharePoint:CssLink ID="CssLink1" runat="server"/>
    <!-- remove support for themes <SharePoint:Theme ID="Theme1" runat="server"/> -->
    <SharePoint:ScriptLink ID="ScriptLink1" language="javascript" name="core.js" Defer="true" runat="server" />
    <SharePoint:CustomJSUrl ID="CustomJSUrl1" runat="server" />
    <SharePoint:SoapDiscoveryLink ID="SoapDiscoveryLink1" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server"/>
    <SharePoint:DelegateControl ID="DelegateControl1" runat="server" ControlId="AdditionalPageHead" AllowMultipleControls="true"/>
</head>
<body scroll="yes" onload="javascript:if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();">

    <form id="Form1" runat="server" onsubmit="return _spFormOnSubmitWrapper();">
        <WebPartPages:SPWebPartManager id="m" runat="Server" />

        <!-- MAIN CONTENT -->
        <div id="main">
            <asp:ContentPlaceHolder id="PlaceHolderMain" runat="server"/>
        </div>

	
<asp:Panel ID="HiddenPlaceholders" visible="false" runat="server">
    <asp:ContentPlaceHolder id="PlaceHolderBodyLeftBorder" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderBodyRightMargin" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderCalendarNavigator" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderFormDigest" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderGlobalNavigation" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderGlobalNavigationSiteMap" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderHorizontalNav" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderLeftActions" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderLeftNavBar" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderLeftNavBarBorder" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderLeftNavBarDataSource" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderLeftNavBarTop" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderMiniConsole" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderNavSpacer" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderPageDescription" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderPageImage" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderPageTitleInTitleArea" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderSiteName" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderTitleAreaSeparator" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderTitleBreadcrumb" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderTitleLeftBorder" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderTitleRightMargin" runat="server" />
    <asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server"/>
    <asp:ContentPlaceHolder ID="SPNavigation" runat="server" />
    <asp:ContentPlaceHolder ID="WSSDesignConsole" runat="server" />
</asp:Panel>            
            
        <input type="text" name="__spDummyText1" style="display:none;" size=1/>
        <input type="text" name="__spDummyText2" style="display:none;" size=1/>
    </form>
    
    <asp:ContentPlaceHolder id="PlaceHolderUtilityContent" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderBodyAreaClass" runat="server"/>
    <asp:ContentPlaceHolder id="PlaceHolderTitleAreaClass" runat="server"/>
</body>
</html>

This minimal master page leads to the following visual.

  SP_Master1_Minimal

 

At this point I took master page from my web server and put it in my minimal SharePoint master page. The trick is to play with SharePoint ContentPlaceHolders. These are all the available placeholders:

 

Placeholder Description
PlaceHolderAdditionalPageHead Additional content that needs to be within the tag of the page, for example, references to script in style sheets
PlaceHolderBodyAreaClass Additional body styles in the page header
PlaceHolderBodyLeftBorder Border element for the main page body
PlaceHolderBodyRightMargin Right margin of the main page body
PlaceHolderCalendarNavigator Shows a date picker for navigating in a calendar when a calendar is visible on the page
PlaceHolderFormDigest The "form digest" security control
PlaceHolderGlobalNavigation The global navigation breadcrumb
PlaceHolderHorizontalNav Top navigation menu for the page
PlaceHolderLeftActions Bottom of the left navigation area
PlaceHolderLeftNavBar Left navigation area
PlaceHolderLeftNavBarBorder Border element on the left navigation bar
PlaceHolderLeftNavBarDataSource Data source for the left navigation menu
PlaceHolderLeftNavBarTop Top of the left navigation area
PlaceHolderMain Page's main content
PlaceHolderMiniConsole A place to show page-level commands, for example, WIKI commands such as Edit Page, History, and Incoming Links
PlaceHolderNavSpacer The width of the left navigation area
PlaceHolderPageDescription Description of the page contents
PlaceHolderPageImage Page icon in the upper left area of the page
PlaceHolderPageTitle The page

 

With this information I have updated the “logo” element:

<!-- LOGO -->
<div id="logo" class="logo">
    <asp:ContentPlaceHolder id="PlaceHolderSiteName" runat="server">
        <SharePoint:SPLinkButton runat="server" NavigateUrl="~site/" id="onetidProjectPropertyTitle" CssClass="whiteLink" >
            David Pokluda's <SharePoint:ProjectProperty ID="ProjectProperty1" Property="Title" runat="server" />
        </SharePoint:SPLinkButton>
    </asp:ContentPlaceHolder>
</div>

 

Here is my “main content” element:

<!-- MAIN TEXT -->
<div id="main">
    <asp:ContentPlaceHolder id="PlaceHolderMain" runat="server" />
</div>

 

I have also added the simple “search” element:

<div id="sn1" class="sidenote">
    <div id="sn1header" class="sidenoteheader">
        Quick Search
    </div>
    <div id="sn1text" class="sidenotetext">
        <asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">
          <SharePoint:DelegateControl ID="DelegateControl5" runat="server" ControlId="SmallSearchInputBox" />
        </asp:ContentPlaceHolder>
    </div>
</div>

 

After updating the CSS file (with styles from my web server) I saw the following visual:

   SP_Master1_Final

 

I think it is pretty good when you consider that it was a simple modification of the master page. (Ok, it is not as simple as I am trying to say here but it is not a rocket science.)

 

Applying the new master page

In the previous section I skipped the part of applying the new master page to the site. You have multiple options for that. The easiest is probably to use SharePoint Designer for that – see Apply the new master page. Another option is to do that programmatically. To do so use the following code:

 

public void ApplyCustomBrand() 
{
    SPWeb site = SPContext.Current.Web;

    string MasterUrlPath = site.ServerRelativeUrl;
    if (!MasterUrlPath.EndsWith(@"/"))
    {
        MasterUrlPath += @"/";
    }
    MasterUrlPath += @"_catalogs/masterpage/Pokluda.master";
    ApplyCustomBrandToWebs(MasterUrlPath, site);

    Response.Redirect(Request.RawUrl);
}

public void ApplyCustomBrandToWebs(string MasterUrlPath, SPWeb site) 
{
    site.ApplyTheme("");
    site.MasterUrl = MasterUrlPath;
    site.AlternateCssUrl = "/_layouts/1033/STYLES/Pokluda/PokludaWebStyle.css";
    site.SiteLogoUrl = "";
    site.Update();

    foreach (SPWeb child in site.Webs) 
    {
        ApplyCustomBrandToWebs(MasterUrlPath, child);
    }
}

 

The above mentioned code is based on CustomBranding project from Chapter 3 of Inside Microsoft Windows SharePoint Services 3.0 book from Ted Pattison and Daniel Larson.

More information:

SharePoint

Connecting to SharePoint embedded database

10. March 2009

As a new member in Windows SharePoint team I am trying to learn as much as possible. I have installed SharePoint (WSS) version 3.0 on my home computer. I wanted to see what is the database schema in SharePoint. Since I had SQL Server 2008 installed on my machine I started SQL Server Management Studio.

 

Connecting to SharePoint SSEE database

 

But when I click Connect I only get the following error:

 

ConnectingToSharePointDb_Error

 

 

 

Bummer. After a while of searching on Internet I found the following Wikipedia article - Windows Internal Database. Let me quote some of the text from the article:

 

Windows Internal Database (codenamed WYukon, sometimes referred to as SQL Server Embedded Edition) is a variant of SQL Server Express 2005 that is included with Windows Server 2008, and is included with other free Microsoft products released after 2007 that require an SQL Server database backend. Windows SharePoint Services 3.0 and Windows Server Update Services 3.0 both include Windows Internal Database, which can be used as an alternative to using a retail edition of SQL Server.

 

Ok, now I know that I am not connecting to a SQL Server database but instead to Windows Internal database. How do I do that? Again Wikipedia has the answer:

 

SQL Server Management Studio Express can be used to connect to an instance of Windows Internal Database using \\.\pipe\mssql$microsoft##ssee\sql\query as server name.

 

That means, that I should be able to connect even from SQL Server 2008 Management Studio.

 

ConnectingToSharePointDb_EmbeddedPipeString

 

That did the trick. I have now SQL Server Management Studio fully connected to the content database and I can execute queries against the database (I can use the same connection with SQL Profiler).

 

ConnectingToSharePointDb_Connected

 

More information can be found at:

SharePoint ,

Windows SharePoint Services

6. March 2009

Ok, it’s not even a month since my first post on this blog and things are different already. I have changed teams and now I work in SharePoint Server organization, in particular in Windows SharePoint Services Storage and Perf team. Since I am new to the team I cannot say for sure what is my primary feature but I hope I will find out soon.

I’m now also on Twitter, you can follow me. I have also added a special side bar with my latest updates from Twitter.

Blog ,