Part 2 – Edit Profile and My Site links
A project I am working on called for a custom implementation of the SharePoint Welcome menu control. The replacement control needed to provide the following:
- Implement the look and behaviors that the designers created.
- Exclude some default SharePoint menu items (such as My Regional Settings).
- Reuse some existing SharePoint menu items (such as Sign Out/Sign in as a Different User).
- Allow for the addition of other custom menu items in the future.
- Display thumbnail of the user’s profile picture.
I had to create a control that looked and behaved like the following:
The designers came up with some clean, semantic markup married with some jquery, for me to start from:
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="header"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">img</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="header-logo"</span> <span style="color: #ff0000">src</span><span style="color: #0000ff">="/images/header_logo.png"</span> <span style="color: #ff0000">alt</span><span style="color: #0000ff">=""</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="169"</span> <span style="color: #ff0000">height</span><span style="color: #0000ff">="78"</span> <span style="color: #0000ff">/></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="header-bar"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="profile_menu"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">a</span> <span style="color: #ff0000">href</span><span style="color: #0000ff">="#"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="profile_btn"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="image"</span><span style="color: #0000ff">><</span><span style="color: #800000">img</span> <span style="color: #ff0000">src</span><span style="color: #0000ff">=""</span> <span style="color: #ff0000">style</span><span style="color: #0000ff">="width:20px;height:20px"</span> <span style="color: #0000ff">/></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="name"</span><span style="color: #0000ff">></span>John Doe<span style="color: #0000ff"></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="arrow"</span><span style="color: #0000ff">></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">a</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="profile_dropdown"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="dropdown_bkgrd"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">ul</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>Edit Profile<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>My Site<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>Log Out<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>Sign in as a Different User<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">ul</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
This is part 2 of a three part series.
Leveraging the SocialNavigationControl for My Site and My Profile links
The My Site and My Profile links are rendered by the SocialNavigationControl, and contain rendering logic that branches depending on whether a My Site host has been installed. I didn’t want to recreate this so I went digging with Reflector.
I found this code for the control’s OnInit method:
1 |
<span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> OnInit(EventArgs e) |
1 |
{ |
1 |
<span style="color: #0000ff">base</span>.OnInit(e); |
1 |
  |
1 |
<span style="color: #0000ff">if</span> (!<span style="color: #0000ff">base</span>.IsPostBack && SocialControlHelper.CheckUserAccess) |
1 |
{ |
1 |
<span style="color: #0000ff">this</span>.ProfileURL = SocialControlHelper.ProfileURL; |
1 |
<span style="color: #0000ff">this</span>.MySiteHostURL = SocialControlHelper.MySiteHostURL; |
1 |
} |
1 |
} |
1 |
  |
Sweet! Everything I needed was right there, from the SocialControlHelper class.
Wait a minute, Doh! SocialControlHelper is marked as sealed, internal. Wonderful, don’t you love it when Microsoft does that?
Fortunately, upon looking at the code for SocialControlHelper, it runs once, and caches the two URLs it’s responsible for in the HttpContext.Items collection using the following string keys:
1 |
<span style="color: #0000ff">private</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> FLD_MySiteHostURL = <span style="color: #006080">"SocialData$MySiteHostURL"</span>; |
1 |
<span style="color: #0000ff">private</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> FLD_ProfileURL = <span style="color: #006080">"SocialData$ProfileURL"</span>; |
1 |
  |
Perfect, anything can grab it from there. The SocialNavigationControl does its rendering of menu items in the OnPreRender event. This means that by including the control on a page, and setting it’s visibility to FALSE, it won’t render anything, and we can still leverage the items in SocialDataHelper by getting the urls from HttpContext.Items. We can add this to our ASCX markup at the top:
1 |
<span style="color: #008000"><!-- The social data control is used here just to test for existence of mysite/profile pages --></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderSocialData"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">><</span><span style="color: #800000">SPSWC:SocialNavigationControl</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="socialNav"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span> <span style="color: #ff0000">Visible</span><span style="color: #0000ff">="false"</span><span style="color: #0000ff">></</span><span style="color: #800000">SPSWC:SocialNavigationControl</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></span> |
1 |
  |
Some ASCX code-behind:
1 |
<span style="color: #0000ff">string</span> myProfileUrl = Context.Items[<span style="color: #006080">"SocialData$ProfileURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
<span style="color: #0000ff">string</span> mySiteHostUrl = Context.Items[<span style="color: #006080">"SocialData$MySiteHostURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
  |
1 |
<span style="color: #0000ff">if</span> (!Page.IsPostBack) |
1 |
{ |
1 |
myProfileUrl = Context.Items[<span style="color: #006080">"SocialData$ProfileURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
ViewState[Constants.VIEWSTATE_PROFILE_URL] = myProfileUrl; |
1 |
mySiteHostUrl = Context.Items[<span style="color: #006080">"SocialData$MySiteHostURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
ViewState[Constants.VIEWSTATE_MYSITE_URL] = mySiteHostUrl; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
myProfileUrl = ViewState[Constants.VIEWSTATE_PROFILE_URL] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
mySiteHostUrl = ViewState[Constants.VIEWSTATE_MYSITE_URL] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
} |
1 |
  |
1 |
<span style="color: #0000ff">if</span> (<span style="color: #0000ff">string</span>.IsNullOrEmpty(mySiteHostUrl)) |
1 |
{ |
1 |
<span style="color: #008000">// No MySite host, or user does not have rights to view profile page...</span> |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
<span style="color: #008000">// User has a MySite, show the link to it...</span> |
1 |
} |
1 |
  |
1 |
<span style="color: #0000ff">if</span> (<span style="color: #0000ff">string</span>.IsNullOrEmpty(myProfileUrl)) |
1 |
{ |
1 |
<span style="color: #008000">// Use the SharePoint foundation profile page, since the MySite host is not available... </span> |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
<span style="color: #008000">// Use the MySite profile page...</span> |
1 |
} |
Notice that I am storing these URLs in ViewState as well. The SocialNavigationControl only fetches data on initial page load. If you have applications/web parts/user controls that will be present during postbacks, then you will want to persist these links somewhere like ViewState.
Reconstructing the SocialNavigationControl’s Javascript
Now for the hard part, filling in the conditionals above. The Welcome menu is comprised of three different controls, so they don’t all render the same way. The primary control, PersonalActions, renders the core menu and the bulk of the menu items in HTML. The SocialNavigationControl, however, uses javascript to find the existing menu on the page and then append its own items to it. It’s pretty ugly and hacky (from Reflector):
1 |
<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> SetMyProfileMenuJavascript() |
1 |
{ |
1 |
<span style="color: #0000ff">string</span> key = <span style="color: #0000ff">this</span>.ClientID + <span style="color: #006080">"_insertMyProfileMenu"</span>; |
1 |
DebugStringBuilder builder = <span style="color: #0000ff">new</span> DebugStringBuilder(); |
1 |
builder.AppendLine(<span style="color: #006080">"function "</span> + key + <span style="color: #006080">"() {"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" var menus = document.getElementsByTagName('menu');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" if (menus == null) return;"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" var menu = null;"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" for (var i=0, len=menus.length; i<len; i++) {"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" if (menus[i].id.lastIndexOf('PersonalActionMenu') != -1) {"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">"tt menu = menus[i]; break;"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" }"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" }"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" if (menu == null) return;"</span>); |
1 |
<span style="color: #0000ff">bool</span> flag = <span style="color: #0000ff">false</span>; |
1 |
<span style="color: #0000ff">bool</span> flag2 = <span style="color: #0000ff">false</span>; |
1 |
<span style="color: #0000ff">if</span> (!<span style="color: #0000ff">string</span>.IsNullOrEmpty(<span style="color: #0000ff">this</span>.ProfileURL)) |
1 |
{ |
1 |
flag = <span style="color: #0000ff">true</span>; |
1 |
builder.AppendLine(<span style="color: #006080">" var elm = document.createElement('ie:menuitem');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm.setAttribute('menugroupid', '50');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm.setAttribute('description', '"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(StringResourceManager.GetString(LocStringId.MyProfileMenu_description)) + <span style="color: #006080">"');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm.setAttribute('text', '"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(StringResourceManager.GetString(LocStringId.MyProfileMenu_text)) + <span style="color: #006080">"');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">@" elm.setAttribute('onmenuclick', 'STSNavigate2(event,'"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(<span style="color: #0000ff">this</span>.ProfileURL) + <span style="color: #006080">@"')');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm.setAttribute('id', 'ID_MySiteLinksMenu');"</span>); |
1 |
} |
1 |
<span style="color: #0000ff">if</span> (!<span style="color: #0000ff">string</span>.IsNullOrEmpty(<span style="color: #0000ff">this</span>.MySiteHostURL)) |
1 |
{ |
1 |
flag2 = <span style="color: #0000ff">true</span>; |
1 |
builder.AppendLine(<span style="color: #006080">" var elm2 = document.createElement('ie:menuitem');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm2.setAttribute('menugroupid', '50');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm2.setAttribute('description', '"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(StringResourceManager.GetString(LocStringId.MultPages_MySite_Description)) + <span style="color: #006080">"');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm2.setAttribute('text', '"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(StringResourceManager.GetString(LocStringId.MultPages_MySite_Label)) + <span style="color: #006080">"');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">@" elm2.setAttribute('onmenuclick', 'STSNavigate2(event,'"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(<span style="color: #0000ff">this</span>.MySiteHostURL) + <span style="color: #006080">@"')');"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" elm2.setAttribute('id', 'ID_MySiteMenu');"</span>); |
1 |
} |
1 |
builder.AppendLine(<span style="color: #006080">" var sep = null;"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" for (var i=0, len=menu.childNodes.length; i<len; i++) {"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" t if (menu.childNodes[i].id == undefined || menu.childNodes[i].id == '') {"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" sep = menu.childNodes[i]; break;"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" }"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" }"</span>); |
1 |
<span style="color: #0000ff">if</span> (flag) |
1 |
{ |
1 |
builder.AppendLine(<span style="color: #006080">" if (sep != null)"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" menu.insertBefore(sep.cloneNode(true), menu.firstChild);"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" menu.insertBefore(elm, menu.firstChild);"</span>); |
1 |
} |
1 |
<span style="color: #0000ff">if</span> (flag2) |
1 |
{ |
1 |
builder.AppendLine(<span style="color: #006080">" if (sep != null)"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" menu.insertBefore(sep.cloneNode(true), menu.firstChild);"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">" menu.insertBefore(elm2, menu.firstChild);"</span>); |
1 |
} |
1 |
builder.AppendLine(<span style="color: #006080">"};"</span>); |
1 |
builder.AppendLine(<span style="color: #006080">"_spBodyOnLoadFunctionNames.push('"</span> + key + <span style="color: #006080">"');"</span>); |
1 |
<span style="color: #0000ff">this</span>.Page.ClientScript.RegisterStartupScript(<span style="color: #0000ff">base</span>.GetType(), key, builder.ToString(), <span style="color: #0000ff">true</span>); |
1 |
} |
1 |
  |
The OOB behavior for the Welcome menu will actually render two profile links if you have SharePoint Server installed:
- My Profile (linking to the My Site Host profile page)
- My Regional Settings (linking to userdisp.aspx, the SharePoint Foundation profile page)
The My Regional Settings link is added by the PersonalActions control (from Reflector):
1 |
PostCacheSubstitutionText text2 = <span style="color: #0000ff">new</span> PostCacheSubstitutionText(); |
1 |
text2.TextType = PostCacheSubstitutionTextType.UserId; |
1 |
text2.PrefixHtml = <span style="color: #006080">"<script type="text/javascript">n//<![CDATA[nvar _spUserId="</span>; |
1 |
text2.SuffixHtml = <span style="color: #006080">";n//]]>n</script>"</span>; |
1 |
<span style="color: #0000ff">this</span>.Controls.Add(text2); |
1 |
SPUser currentUser = <span style="color: #0000ff">this</span>.Web.CurrentUser; |
1 |
MenuItemTemplate menuItem = <span style="color: #0000ff">base</span>.GetMenuItem(<span style="color: #006080">"ID_PersonalInformation"</span>); |
1 |
<span style="color: #0000ff">if</span> (menuItem != <span style="color: #0000ff">null</span>) |
1 |
{ |
1 |
<span style="color: #0000ff">if</span> (currentUser == <span style="color: #0000ff">null</span>) |
1 |
{ |
1 |
menuItem.Visible = <span style="color: #0000ff">false</span>; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
<span style="color: #0000ff">string</span> serverRelativeUrlFromUrl = <span style="color: #0000ff">this</span>.Web.GetServerRelativeUrlFromUrl(<span style="color: #006080">"_layouts/userdisp.aspx?Force=True&ID="</span>); |
1 |
menuItem.ClientOnClickScript = <span style="color: #006080">"javascript:GoToPage('"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(serverRelativeUrlFromUrl) + <span style="color: #006080">"' + _spUserId);return false;"</span>; |
1 |
} |
1 |
} |
My design called for only displaying one “Edit Profile” link, which should be smart enough to combine these two approaches, and link to userdisp.aspx if SharePoint Foundation used, and to the My Site Host profile page if available.
To achieve this, the first step is to adjust the ASCX markup to include some PlaceHolder controls that can be customized in code-behind:
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="profile_dropdown"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderUserID"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="dropdown_bkgrd"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">ul</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderEditProfile"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">><</span><span style="color: #800000">li</span><span style="color: #0000ff">><</span><span style="color: #800000">asp:LinkButton</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="linkButtonEditProfile"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span> <span style="color: #ff0000">EnableViewState</span><span style="color: #0000ff">="false"</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">="Edit Profile"</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:LinkButton</span><span style="color: #0000ff">></</span><span style="color: #800000">li</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderMySite"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">><</span><span style="color: #800000">li</span><span style="color: #0000ff">><</span><span style="color: #800000">asp:LinkButton</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="linkButtonMySite"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span> <span style="color: #ff0000">EnableViewState</span><span style="color: #0000ff">="false"</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">="My Site"</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:LinkButton</span><span style="color: #0000ff">></</span><span style="color: #800000">li</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>Log Out<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>Sign in as a Different User<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">ul</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
Here is the code-behind I used that combines the output from the PersonalActions control and SocialNavigationControl:
1 |
<span style="color: #0000ff">string</span> myProfileUrl = Context.Items[<span style="color: #006080">"SocialData$ProfileURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
<span style="color: #0000ff">string</span> mySiteHostUrl = Context.Items[<span style="color: #006080">"SocialData$MySiteHostURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
  |
1 |
<span style="color: #0000ff">if</span> (!Page.IsPostBack) |
1 |
{ |
1 |
myProfileUrl = Context.Items[<span style="color: #006080">"SocialData$ProfileURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
ViewState[Constants.VIEWSTATE_PROFILE_URL] = myProfileUrl; |
1 |
mySiteHostUrl = Context.Items[<span style="color: #006080">"SocialData$MySiteHostURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
ViewState[Constants.VIEWSTATE_MYSITE_URL] = mySiteHostUrl; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
myProfileUrl = ViewState[Constants.VIEWSTATE_PROFILE_URL] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
mySiteHostUrl = ViewState[Constants.VIEWSTATE_MYSITE_URL] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
} |
1 |
  |
1 |
<span style="color: #0000ff">if</span> (<span style="color: #0000ff">string</span>.IsNullOrEmpty(mySiteHostUrl)) |
1 |
{ |
1 |
<span style="color: #008000">// No MySite host, or user does not have rights to view profile page...</span> |
1 |
placeHolderMySite.Visible = <span style="color: #0000ff">false</span>; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
<span style="color: #008000">// User has a MySite, show the link to it...</span> |
1 |
placeHolderMySite.Visible = <span style="color: #0000ff">true</span>; |
1 |
linkButtonMySite.OnClientClick = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"STSNavigate2(event, '{0}');return false;"</span>, SPHttpUtility.EcmaScriptStringLiteralEncode(mySiteHostUrl)); |
1 |
} |
1 |
<span style="color: #0000ff">if</span> (<span style="color: #0000ff">string</span>.IsNullOrEmpty(myProfileUrl)) |
1 |
{ |
1 |
<span style="color: #008000">// Use the SharePoint foundation profile page, since the MySite host is not available</span> |
1 |
PostCacheSubstitutionText pt = <span style="color: #0000ff">new</span> PostCacheSubstitutionText(); |
1 |
pt.TextType = PostCacheSubstitutionTextType.UserId; |
1 |
pt.PrefixHtml = <span style="color: #006080">"<script type="text/javascript">n//<![CDATA[nvar _spUserId="</span>; |
1 |
pt.SuffixHtml = <span style="color: #006080">";n//]]>n</script>"</span>; |
1 |
placeHolderUserID.Controls.Add(pt); |
1 |
<span style="color: #0000ff">string</span> serverRelativeUrlFromUrl = <span style="color: #0000ff">this</span>.ResolveClientUrl(<span style="color: #006080">"~/_layouts/userdisp.aspx?Force=True&ID="</span>); |
1 |
linkButtonEditProfile.OnClientClick = <span style="color: #006080">"GoToPage('"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(serverRelativeUrlFromUrl) + <span style="color: #006080">"' + _spUserId);return false;"</span>; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
<span style="color: #008000">// Use the MySite profile page...</span> |
1 |
linkButtonEditProfile.OnClientClick = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"STSNavigate2(event, '{0}');return false;"</span>, SPHttpUtility.EcmaScriptStringLiteralEncode(myProfileUrl)); |
1 |
} |
Summary
In this post, we deconstructed the SocialNavigationControl, and figured out how to render intelligent links to My Site and My Profile pages.
Our ASCX markup so far is:
1 |
<span style="background-color: #ffff00"><%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %></span> |
1 |
<span style="background-color: #ffff00"><%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %></span> |
1 |
<span style="background-color: #ffff00"><%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %></span> |
1 |
<span style="background-color: #ffff00"><%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %></span> |
1 |
<span style="background-color: #ffff00"><%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %></span> |
1 |
<span style="background-color: #ffff00"><%@ Import Namespace="Microsoft.SharePoint" %></span> |
1 |
<span style="background-color: #ffff00"><%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %></span> |
1 |
<span style="background-color: #ffff00"><%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CustomWelcomeMenuControl.ascx.cs" Inherits="CustomWelcomeMenu.ControlTemplates.CustomWelcomeMenu.CustomWelcomeMenuControl" %></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="header"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">img</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="header-logo"</span> <span style="color: #ff0000">src</span><span style="color: #0000ff">="/images/header_logo.png"</span> <span style="color: #ff0000">alt</span><span style="color: #0000ff">=""</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="169"</span> <span style="color: #ff0000">height</span><span style="color: #0000ff">="78"</span> <span style="color: #0000ff">/></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="header-bar"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="profile_menu"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">a</span> <span style="color: #ff0000">href</span><span style="color: #0000ff">="#"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="profile_btn"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="image"</span><span style="color: #0000ff">><</span><span style="color: #800000">asp:Image</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="imageProfilePicture"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span> <span style="color: #ff0000">Width</span><span style="color: #0000ff">="20px"</span> <span style="color: #ff0000">Height</span><span style="color: #0000ff">="20px"</span> <span style="color: #0000ff">/></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="name"</span><span style="color: #0000ff">><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderWelcomeName"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="arrow"</span><span style="color: #0000ff">></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">a</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="profile_dropdown"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderUserID"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="dropdown_bkgrd"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">ul</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderEditProfile"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">><</span><span style="color: #800000">li</span><span style="color: #0000ff">><</span><span style="color: #800000">asp:LinkButton</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="linkButtonEditProfile"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span> <span style="color: #ff0000">EnableViewState</span><span style="color: #0000ff">="false"</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">="Edit Profile"</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:LinkButton</span><span style="color: #0000ff">></</span><span style="color: #800000">li</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">asp:PlaceHolder</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="placeHolderMySite"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span><span style="color: #0000ff">><</span><span style="color: #800000">li</span><span style="color: #0000ff">><</span><span style="color: #800000">asp:LinkButton</span> <span style="color: #ff0000">ID</span><span style="color: #0000ff">="linkButtonMySite"</span> <span style="color: #ff0000">runat</span><span style="color: #0000ff">="server"</span> <span style="color: #ff0000">EnableViewState</span><span style="color: #0000ff">="false"</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">="My Site"</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:LinkButton</span><span style="color: #0000ff">></</span><span style="color: #800000">li</span><span style="color: #0000ff">></</span><span style="color: #800000">asp:PlaceHolder</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>Log Out<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"><</span><span style="color: #800000">li</span><span style="color: #0000ff">></span>Sign in as a Different User<span style="color: #0000ff"></</span><span style="color: #800000">li</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">ul</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> |
1 |
  |
Our ASCX code-behind so far is:
1 |
<span style="color: #0000ff">using</span> System; |
1 |
<span style="color: #0000ff">using</span> System.Web.UI; |
1 |
<span style="color: #0000ff">using</span> System.Web.UI.WebControls; |
1 |
<span style="color: #0000ff">using</span> System.Web.UI.WebControls.WebParts; |
1 |
<span style="color: #0000ff">using</span> Microsoft.SharePoint; |
1 |
<span style="color: #0000ff">using</span> Microsoft.SharePoint.WebControls; |
1 |
<span style="color: #0000ff">using</span> Microsoft.SharePoint.Utilities; |
1 |
  |
1 |
<span style="color: #0000ff">namespace</span> CustomWelcomeMenu.ControlTemplates.CustomWelcomeMenu |
1 |
{ |
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">partial</span> <span style="color: #0000ff">class</span> CustomWelcomeMenuControl : UserControl |
1 |
{ |
1 |
<span style="color: #0000ff">protected</span> <span style="color: #0000ff">void</span> Page_PreRender(<span style="color: #0000ff">object</span> sender, EventArgs e) |
1 |
{ |
1 |
1 |
<span style="color: #008000">// Username</span> |
1 |
PostCacheSubstitutionText welcomeText = <span style="color: #0000ff">new</span> PostCacheSubstitutionText(); |
1 |
welcomeText.TextType = PostCacheSubstitutionTextType.UserName; |
1 |
placeHolderWelcomeName.Controls.Add(welcomeText); |
1 |
  |
1 |
<span style="color: #008000">// Profile picture</span> |
1 |
SPList userInfoList = SPContext.Current.Web.GetCatalog(SPListTemplateType.UserInformation); |
1 |
SPListItem userProfileItem = userInfoList.GetItemById(SPContext.Current.Web.CurrentUser.ID); |
1 |
<span style="color: #0000ff">if</span> (userProfileItem[<span style="color: #006080">"Picture"</span>] == <span style="color: #0000ff">null</span> || <span style="color: #0000ff">string</span>.IsNullOrEmpty(userProfileItem[<span style="color: #006080">"Picture"</span>].ToString())) |
1 |
{ |
1 |
<span style="color: #008000">// Use default picture (or replace with another)</span> |
1 |
imageProfilePicture.ImageUrl = <span style="color: #006080">"/_layouts/images/PERSON.GIF"</span>; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
SPFieldUrlValue <span style="color: #0000ff">value</span> = <span style="color: #0000ff">new</span> SPFieldUrlValue(userProfileItem[<span style="color: #006080">"Picture"</span>].ToString()); |
1 |
imageProfilePicture.ImageUrl = <span style="color: #0000ff">value</span>.Url; |
1 |
} |
1 |
  |
1 |
<span style="color: #0000ff">string</span> myProfileUrl = Context.Items[<span style="color: #006080">"SocialData$ProfileURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
<span style="color: #0000ff">string</span> mySiteHostUrl = Context.Items[<span style="color: #006080">"SocialData$MySiteHostURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
1 |
<span style="color: #0000ff">if</span> (!Page.IsPostBack) |
1 |
{ |
1 |
myProfileUrl = Context.Items[<span style="color: #006080">"SocialData$ProfileURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
ViewState[Constants.VIEWSTATE_PROFILE_URL] = myProfileUrl; |
1 |
mySiteHostUrl = Context.Items[<span style="color: #006080">"SocialData$MySiteHostURL"</span>] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
ViewState[Constants.VIEWSTATE_MYSITE_URL] = mySiteHostUrl; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
myProfileUrl = ViewState[Constants.VIEWSTATE_PROFILE_URL] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
mySiteHostUrl = ViewState[Constants.VIEWSTATE_MYSITE_URL] <span style="color: #0000ff">as</span> <span style="color: #0000ff">string</span>; |
1 |
} |
1 |
1 |
1 |
<span style="color: #0000ff">if</span> (<span style="color: #0000ff">string</span>.IsNullOrEmpty(mySiteHostUrl)) |
1 |
{ |
1 |
<span style="color: #008000">// No MySite host, or user does not have rights to view profile page...</span> |
1 |
placeHolderMySite.Visible = <span style="color: #0000ff">false</span>; |
1 |
  |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
<span style="color: #008000">// User has a MySite, show the link to it...</span> |
1 |
placeHolderMySite.Visible = <span style="color: #0000ff">true</span>; |
1 |
linkButtonMySite.OnClientClick = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"STSNavigate2(event, '{0}');return false;"</span>, SPHttpUtility.EcmaScriptStringLiteralEncode(mySiteHostUrl)); |
1 |
} |
1 |
1 |
<span style="color: #0000ff">if</span> (<span style="color: #0000ff">string</span>.IsNullOrEmpty(myProfileUrl)) |
1 |
{ |
1 |
<span style="color: #008000">// Use the SharePoint foundation profile page, since the MySite host is not available</span> |
1 |
PostCacheSubstitutionText pt = <span style="color: #0000ff">new</span> PostCacheSubstitutionText(); |
1 |
pt.TextType = PostCacheSubstitutionTextType.UserId; |
1 |
pt.PrefixHtml = <span style="color: #006080">"<script type="text/javascript">n//<![CDATA[nvar _spUserId="</span>; |
1 |
pt.SuffixHtml = <span style="color: #006080">";n//]]>n</script>"</span>; |
1 |
placeHolderUserID.Controls.Add(pt); |
1 |
<span style="color: #0000ff">string</span> serverRelativeUrlFromUrl = <span style="color: #0000ff">this</span>.ResolveClientUrl(<span style="color: #006080">"~/_layouts/userdisp.aspx?Force=True&ID="</span>); |
1 |
linkButtonEditProfile.OnClientClick = <span style="color: #006080">"GoToPage('"</span> + SPHttpUtility.EcmaScriptStringLiteralEncode(serverRelativeUrlFromUrl) + <span style="color: #006080">"' + _spUserId);return false;"</span>; |
1 |
} |
1 |
<span style="color: #0000ff">else</span> |
1 |
{ |
1 |
<span style="color: #008000">// Use the MySite profile page...</span> |
1 |
linkButtonEditProfile.OnClientClick = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"STSNavigate2(event, '{0}');return false;"</span>, SPHttpUtility.EcmaScriptStringLiteralEncode(myProfileUrl)); |
1 |
} |
1 |
  |
1 |
} |
1 |
} |
1 |
} |
Next, check out Part 3, where we learn how to display links to Sign Out and Sign in as a Different User.