Use Layout Pages Metadata (properties) in the Master Page
This post is a tribute to my colleague Riad TIZERARINE that has found this tip. We had to use some of the properties of the layout Pages inside the master page. We wanted precisely to take the value of the field description of the Layout Page, and put it inside the meta tag "description.
So I will illustrate the elegant solution that have found Riad in a short tutorial and will show that this practice can be extended.
1 - Create a minimal master page and put it in the master page gallery
I usually work on master pages starting with minimal one as recommanded by Microsoft :How to: Create a Minimal Master Page
So I did a feature in order to deploy this master page and let it to the ghosted state because I want to use visual studio to customize it.
When I have deployed this master page in the master page gallery, and change it for my Litware portal root site, I obtain this result.

2 - populate your publishing page fields
Now I have to populate my publishing page fields in order to have data to use in the demonstration.
3 - Programming with C# in line script
So the idea now is to use the metadata of the page layout inside the master page to display informations that are stored at the Layout Page level, but WITHOUT writing a single line of code in the layout page.
We will illustrate this by using description porperty of the layout page in a meta tag description, and using ["Modified By"], [Modified"] and Page Layout Contact e-mail to populate the footer of the master page.
So how to do it in an elegant way?
Riad found the solution with this instruction:
SPcontext.Current.File
MSDN doesn't teach so much about this instruction : Gets the file that is associated with the list item object of the given Windows SharePoint Services context. (SPContext Members (Microsoft.SharePoint))
here is the sample that show how to use it :
To put the page layout descrption inside a meta tag description, put this in line script right under the meta tag of your master page.
<% SPFile myPublishingPage = SPContext.Current.File;
string description = string.Empty;
if (myPublishingPage.Item.Fields.ContainsField("Description"))
{
description = (string)myPublishingPage.Item["Description"];
}
%>
<meta name="Description" content="<%=description %>" />
And there is a much more simple way :
<% SPItem myPublishingPageItem = SPContext.Current.Item;
string description = string.Empty;
if (myPublishingPageItem.Fields.ContainsField("Description"))
{
description = (string)myPublishingPageItem["Description"];
}
%>
<meta name="Description" content="<%=description %>" />
Here is the in line script and html code to render the footer using layout page properties as previously defined
Warnings:
Place your in line script after the form tag otherwise it will not be working.
And as usual, don't forget that in line script in master page is just a temporary solution, to make a proof of concept, and not a best practice for real applications.
<%
char[] separator = { '#' };
string strMyUser = string.Empty;
strMyUser = myPublishingPageItem["Modified By"].ToString().Split(separator)[1];
char[] separator2 = { '(' };
string[] maTable;
strMyUser = strMyUser.Split(separator2)[0];
string creationDate = string.Empty;
creationDate = myPublishingPageItem["Modified"].ToString();
string authorEmail = string.Empty;
if (myPublishingPageItem.Fields.ContainsField("Contact E-Mail Address"))
{
authorEmail = (string)myPublishingPageItem["Contact E-Mail Address"];
}
%>
<br />
<div style="width: 100%; text-align: center; color: #5B5B5B; font-family: Tahoma;
font-size: 8pt;">
<table id="footer" style="width: 600px; border: solid 1px #5B5B5B; border-collapse: collapse">
<tr>
<td style="text-align: center; width: 200px">
Modified by: <%=strMyUser%></td>
<td>
| </td>
<td width="200px">
At
<%=creationDate %>
</td>
<td>
| </td>
<td width="200px">
<a href="mailto:<%=authorEmail%>">contact us</a></td>
</tr>
</table>
</div>
4 - Results
Here is the new home page with the footer after the implementation:
Here is the complete code of the minimal master page after the implementation:
<%-- Identifies this page as a .master page written in Microsoft Visual C# and registers tag prefixes, namespaces, assemblies, and controls. --%>
<%@ Master Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Register TagPrefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls"
Assembly="Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
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="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls"
Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation"
Assembly="Microsoft.SharePoint.Publishing, 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" %>
<%@ Register TagPrefix="PublishingVariations" TagName="VariationsLabelMenu" Src="~/_controltemplates/VariationsLabelMenu.ascx" %>
<%@ Register TagPrefix="PublishingConsole" TagName="Console" Src="~/_controltemplates/PublishingConsole.ascx" %>
<%@ Register TagPrefix="PublishingSiteAction" TagName="SiteActionMenu" Src="~/_controltemplates/PublishingActionMenu.ascx" %>
<%-- Uses the Microsoft Office namespace and schema. --%>
<html>
<WebPartPages:SPWebPartManager runat="server" />
<SharePoint:RobotsMetaTag runat="server" />
<% SPItem myPublishingPageItem = SPContext.Current.Item;
string description = string.Empty;
if (myPublishingPageItem.Fields.ContainsField("Description"))
{
description = (string)myPublishingPageItem["Description"];
}
%>
<meta name="Description" content="<%=description %>" />
<%-- The head section includes a content placeholder for the page title and links to CSS and ECMAScript (JScript, JavaScript) files that run on the server. --%>
<head runat="server">
<asp:contentplaceholder runat="server" id="head">
<title>
<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server" />
</title>
</asp:contentplaceholder>
<SharePoint:CssLink runat="server" />
<asp:contentplaceholder id="PlaceHolderAdditionalPageHead" runat="server" />
</head>
<%-- When loading the body of the .master page, SharePoint Server 2007 also loads the SpBodyOnLoadWrapper class. This class handles .js calls for the master page. --%>
<body onload="javascript:_spBodyOnLoadWrapper();">
<%-- The SPWebPartManager manages all of the Web part controls, functionality, and events that occur on a Web page. --%>
<form runat="server" onsubmit="return _spFormOnSubmitWrapper();">
<wssuc:Welcome id="explitLogout" runat="server" />
<PublishingSiteAction:SiteActionMenu runat="server" />
<PublishingWebControls:AuthoringContainer ID="authoringcontrols" runat="server">
<PublishingConsole:Console runat="server" />
</PublishingWebControls:AuthoringContainer>
<%-- The PlaceHolderMain content placeholder defines where to place the page content for all the content from the page layout. The page layout can overwrite any content placeholder from the master page. Example: The PlaceHolderLeftNavBar can overwrite the left navigation bar. --%>
<asp:ContentPlaceHolder ID="PlaceHolderMain" runat="server" />
<asp:Panel Visible="false" runat="server">
<%-- These ContentPlaceHolders ensure all default SharePoint Server pages render with this master page. If the system master page is set to any default master page, the only content placeholders required are those that are overridden by your page layouts. --%>
<asp:ContentPlaceHolder ID="PlaceHolderSearchArea" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderTitleBreadcrumb" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderPageTitleInTitleArea" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderLeftNavBar" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderPageImage" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderBodyLeftBorder" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderNavSpacer" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderTitleLeftBorder" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderTitleAreaSeparator" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderMiniConsole" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderCalendarNavigator" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderLeftActions" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderPageDescription" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderBodyAreaClass" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderTitleAreaClass" runat="server" />
<asp:ContentPlaceHolder ID="PlaceHolderBodyRightMargin" runat="server" />
</asp:Panel>
</form>
<%
/*//Use that if you want to explore the page properties
Response.Write("<Table style='border-collapse:collapse;'>");
System.Collections.Generic.SortedDictionary<string, string> myList = new System.Collections.Generic.SortedDictionary<string, string>();
foreach (SPField aField in myPublishingPageItem.Fields)
{
try
{
myList.Add(aField.ToString(), myPublishingPageItem[aField.ToString()].ToString());
}
catch
{
}
}
foreach (string aString in myList.Keys)
{
Response.Write("<tr ><td nowrap style='margin:0px;width:300px;border:solid 1px gray;font-size:9pt;'>" + aString + "</td><td nowrap style='border:solid 1px gray;font-size:9pt;'>" + myList[aString] + "</td></tr>");
}
Response.Write("</Table>");*/
char[] separator = { '#' };
string strMyUser = string.Empty;
strMyUser = myPublishingPageItem["Modified By"].ToString().Split(separator)[1];
char[] separator2 = { '(' };
string[] maTable;
strMyUser = strMyUser.Split(separator2)[0];
string creationDate = string.Empty;
creationDate = myPublishingPageItem["Modified"].ToString();
string authorEmail = string.Empty;
if (myPublishingPageItem.Fields.ContainsField("Contact E-Mail Address"))
{
authorEmail = (string)myPublishingPageItem["Contact E-Mail Address"];
}
%>
<br />
<div style="width: 100%; text-align: center; color: #5B5B5B; font-family: Tahoma;
font-size: 8pt;">
<table id="footer" style="width: 600px; border: solid 1px #5B5B5B; border-collapse: collapse">
<tr>
<td style="text-align: center; width: 200px">
Modified by: <%=strMyUser%></td>
<td>
| </td>
<td width="200px">
At
<%=creationDate %>
</td>
<td>
| </td>
<td width="200px">
<a href="mailto:<%=authorEmail%>">contact us</a></td>
</tr>
</table>
</div>
</body>
</html>
No comments:
Post a Comment