Tuesday, January 10, 2006

Extreme SharePoint Design: Custom MySite Titles, Part 2

In a previous post I demonstrated how to create custom titles on MySite pages that display the site owner's name and link back to the public view if the viewer is just a reader and the private view if the viewer is the site owner. The example used the Title property of the SPControl.GetContextWeb(Context) method to retrieve the site owner's name from AD. This works fine if the correct fields in AD have the right information in the right format (i.e First Name, Middle Initial, Last Name) but not so well if they don't. In many cases, the system returns the user name in the Windows default format of [Domain]\[Username].

Fortunately, SharePoint user profiles contain the user's full name, which is rendered in the <SPSWC:PersonalSpaceMainHeading> control; unfortunately, this information is not directly accessible via the object model and, like the Title property, the name is displayed in the 'Last Name, First Name' format. To further complicate matters, the PersonalSpaceMainHeading control insists on displaying an icon that indicates whether or not the user is logged into the system, even if the RenderPawn option is set to 'False'.

To circumvent these issues and insure that the user name is rendered as 'First Name, Last Name' in all instances, we'll first hide the <SPSWC:PersonalSpaceMainHeading> control on the page, then access it's innerText property to get the user name. Then we'll parse the user name into the correct format and apply logic to determine whether the user is a reader or site owner and then write out the proper link.

First, create a blank user control (server and client-side code are blocked from execution in a standard portal page) with the following registrations:

<%@ Control Language="c#" AutoEventWireup="false" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Store the control in the /bin directory of your SharePoint virtual server. For this example, the control is named 'spsTitle_MySite.ascx'.

Next, create the container code for the display of the user name. For this application, we are simply enclosing the user name in a table with two cells: one that reads 'Personal Site' and one that displays the user name. Place the <SPSWC:PersonalSpaceMainHeading> control into a hidden DIV so it can be accessed later in the code:

<table align="left" cellpadding="0" cellspacing="0" border="0">
<tr>
<td width="5"></td>
<td valign="middle" class="Mysite">Personal Site</td>
<td valign="middle" class="Mysite_Title"><div id="PersonalSpaceMainHeading" style="display:none"><SPSWC:PersonalSpaceMainHeading RenderPawn="false" runat="server" /></div></td>
</tr>
</table>

Next, combine a server-side 'If...Then' statement with client-side Javascript which extracts the innerText of the PersonalSpaceMainHeading control and renders the user name and correct link:

<% if (SPControl.GetContextWeb(Context).CurrentUser.LoginName == SPControl.GetContextWeb(Context).Author.LoginName) { %>
<script>
var strFullName = document.getElementById("PersonalSpaceMainHeading").innerText;
var intLength = strFullName.length;
var intLocation = strFullName.indexOf(", ");
if (intLocation == -1)
{
strTitle = strFullName;
}
else
{
strTitle = strFullName.substring(intLocation + 1) + " " + strFullName.substring(0, intLocation);
}
document.write("<a href='/mysite/default.aspx'>" + strTitle + "</a>");
</script>
<% } else { %>
<script>
var strFullName = document.getElementById("PersonalSpaceMainHeading").innerText;
var strUrl = window.location.href;
var intLength = strFullName.length;
var intLocation = strFullName.indexOf(", ");
if (intLocation == -1)
{
strTitle = strFullName;
}
else
{
strTitle = strFullName.substring(intLocation + 1) + " " + strFullName.substring(0, intLocation);

}
document.write("<a href='" + strUrl + "'>" + strTitle + "</a>");
</script>
<% } %>

The first part of the 'If...' statement checks to see if the current user name matches the login name of the site author. Since personal sites are created by the user, the Author will always be the site owner. If the name matches, the subsequent javascript extracts the user name, parses out the comma and reverses the last name and first name (the full name is displayed in the 'Last Name, First Name' format by default). It then creates a hyperlink to the default (private view) of the personal site.

If the current user is not the author, the second javascript performs the same string manipulation then writes out the hyperlink using the public view URL (i.e. "/mysite/public.aspx?accountname=[UserID]"). This method will also work on shared and private libraries, personal pages, and lists, sending the user to the proper home page depending upon their role.

Now we'll need to call the user control from DEFAULT.ASPX and PUBLIC.ASPX. First, add a registration for your new control to the top of each page:

<%@ Register Tagprefix="UC" Tagname="spsTitle_MySite" src="/bin/spsTitle_MySite.ascx" %>

Next, call the control from the body of the page:

<td align="left" valign="middle">
<UC:spsTitle_MySite id="spsTitle_MySite" runat="server"></UC:spsTitle_MySite>
</td>

The final output looks something like this (you can modify the styles to render the link however you wish):