Nov 02 2010

Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 3

Category: ASP.NET, SharePoint, TechnologyAdam Toth @ 4:20 pm

Part 3 – Sign Out/Sign in as a Different User

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:

CropperCapture2_thumb1_thumb

The designers came up with some clean, semantic markup married with some jquery, for me to start from:

<div class="header">

    <img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />

    <div class="header-bar">

        <div class="profile_menu">

            <a href="#" class="profile_btn">

                <span class="image"><img src="" style="width:20px;height:20px" /></span>

                <span class="name">John Doe</span>

                <span class="arrow"></span>

            </a>

            <div class="profile_dropdown">

                <div class="dropdown_bkgrd">

                    <ul>

                        <li>Edit Profile</li> 

                        <li>My Site</li>

                        <li>Log Out</li>                        

                        <li>Sign in as a Different User</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

</div>

This is part 3 of a three part series.

  1. Part 1 – Overview, Profile Picture, and User Name
  2. Part 2 – Edit Profile and My Site links
  3. Part 3 – Sign Out/Sign in as a Different User

Building the Sign Out Links

The Sign Out and Sign in as a Different User menu items are rendered by the PersonalActions control, in two methods (from Reflector):

private void SetLoginAsDifferentUserMenuItemGoToPageUrl()

{

    MenuItemTemplate menuItem = base.GetMenuItem("ID_LoginAsDifferentUser");

    if (menuItem != null)

    {

        if (SPSecurity.AuthenticationMode == AuthenticationMode.None)

        {

            menuItem.Visible = false;

        }

        else

        {

            string serverRelativeUrlFromUrl = this.Web.GetServerRelativeUrlFromUrl("_layouts/closeConnection.aspx?loginasanotheruser=true");

            menuItem.ClientOnClickScript = "javascript:LoginAsAnother('" + SPHttpUtility.EcmaScriptStringLiteralEncode(serverRelativeUrlFromUrl) + "', 0)";

        }

    }

}

 

private void SetSignOutMenuItemGoToPageUrl()

{

    MenuItemTemplate menuItem = base.GetMenuItem("ID_Logout");

    if (menuItem != null)

    {

        if (SPSecurity.AuthenticationMode == AuthenticationMode.None)

        {

            menuItem.Visible = false;

        }

        else

        {

            menuItem.ClientOnClickNavigateUrl = this.Web.GetServerRelativeUrlFromUrl("_layouts/SignOut.aspx");

        }

    }

}

 

 

 

The “Sign Out” link points to “_layouts/SignOut.aspx”, and “Sign in as a Different User” points to “_layouts/closeConnection.aspx”.

To leverage this, I again adjusted the ASCX markup to include some PlaceHolder and LinkButton controls:

<div class="profile_dropdown">

<asp:PlaceHolder ID="placeHolderUserID" runat="server"></asp:PlaceHolder>

    <div class="dropdown_bkgrd">

        <ul>

            <asp:PlaceHolder ID="placeHolderEditProfile" runat="server"><li><asp:LinkButton ID="linkButtonEditProfile" runat="server" EnableViewState="false" Text="Edit Profile"></asp:LinkButton></li></asp:PlaceHolder> 

            <asp:PlaceHolder ID="placeHolderMySite" runat="server"><li><asp:LinkButton ID="linkButtonMySite" runat="server" EnableViewState="false" Text="My Site"></asp:LinkButton></li></asp:PlaceHolder>

            <li><asp:LinkButton ID="linkButtonLogOut" runat="server" EnableViewState="false" Text="Sign Out"></asp:LinkButton></li>                        

            <li><asp:LinkButton ID="linkButtonLoginAsDifferentUser" runat="server" EnableViewState="false" Text="Sign in as a Different User"></asp:LinkButton></li>

        </ul>

    </div>

</div>

And then here is some code-behind that re-creates the output from the PersonalActions control:

// Login as another user

string loginAsAnotherUserUrl = this.ResolveClientUrl("~/_layouts/closeConnection.aspx?loginasanotheruser=true");

linkButtonLoginAsDifferentUser.OnClientClick = string.Format("LoginAsAnother('{0}', 0);return false;", SPHttpUtility.EcmaScriptStringLiteralEncode(loginAsAnotherUserUrl));   

 

// Sign out

string signOutUrl = this.ResolveClientUrl("~/_layouts/SignOut.aspx");

linkButtonLogOut.OnClientClick = "GoToPage('" + SPHttpUtility.EcmaScriptStringLiteralEncode(signOutUrl) + "');return false;";

Summary

In this post, we deconstructed the PersonalActions control further to re-create the Sign Out and Sign in as a Different User menu items.

Our Final ASCX markup is:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>

<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>

<%@ Import Namespace="Microsoft.SharePoint" %> 

<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CustomWelcomeMenuControl.ascx.cs" Inherits="CustomWelcomeMenu.ControlTemplates.CustomWelcomeMenu.CustomWelcomeMenuControl" %>

<div class="header">

    <img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />

    <div class="header-bar">

        <div class="profile_menu">

        <a href="#" class="profile_btn">

            <span class="image"><asp:Image ID="imageProfilePicture" runat="server" Width="20px" Height="20px" /></span>

            <span class="name"><asp:PlaceHolder ID="placeHolderWelcomeName" runat="server"></asp:PlaceHolder></span>

            <span class="arrow"></span>

        </a>

            <div class="profile_dropdown">

                <asp:PlaceHolder ID="placeHolderUserID" runat="server"></asp:PlaceHolder>

                <div class="dropdown_bkgrd">

                    <ul>

                        <asp:PlaceHolder ID="placeHolderEditProfile" runat="server"><li><asp:LinkButton ID="linkButtonEditProfile" runat="server" EnableViewState="false" Text="Edit Profile"></asp:LinkButton></li></asp:PlaceHolder> 

                        <asp:PlaceHolder ID="placeHolderMySite" runat="server"><li><asp:LinkButton ID="linkButtonMySite" runat="server" EnableViewState="false" Text="My Site"></asp:LinkButton></li></asp:PlaceHolder>

                        <li><asp:LinkButton ID="linkButtonLogOut" runat="server" EnableViewState="false" Text="Sign Out"></asp:LinkButton></li>                        

                        <li><asp:LinkButton ID="linkButtonLoginAsDifferentUser" runat="server" EnableViewState="false" Text="Sign in as a Different User"></asp:LinkButton></li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

</div>

Our Final ASCX code-behind is:

using System;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

using Microsoft.SharePoint.Utilities;

 

namespace CustomWelcomeMenu.ControlTemplates.CustomWelcomeMenu

{

    public partial class CustomWelcomeMenuControl : UserControl

    {

        protected void Page_PreRender(object sender, EventArgs e)

        {    

    

            // Username

            PostCacheSubstitutionText welcomeText = new PostCacheSubstitutionText();

            welcomeText.TextType = PostCacheSubstitutionTextType.UserName;

            placeHolderWelcomeName.Controls.Add(welcomeText);

 

            // Profile picture

            SPList userInfoList = SPContext.Current.Web.GetCatalog(SPListTemplateType.UserInformation);

            SPListItem userProfileItem = userInfoList.GetItemById(SPContext.Current.Web.CurrentUser.ID);

            if (userProfileItem["Picture"] == null || string.IsNullOrEmpty(userProfileItem["Picture"].ToString()))

            {

                // Use default picture (or replace with another)

                imageProfilePicture.ImageUrl = "/_layouts/images/PERSON.GIF";

            }

            else

            {

                SPFieldUrlValue value = new SPFieldUrlValue(userProfileItem["Picture"].ToString());

                imageProfilePicture.ImageUrl = value.Url;

            }

 

                string myProfileUrl = Context.Items["SocialData$ProfileURL"] as string;

            string mySiteHostUrl = Context.Items["SocialData$MySiteHostURL"] as string;

    

            if (!Page.IsPostBack)

            {

                myProfileUrl = Context.Items["SocialData$ProfileURL"] as string;

                ViewState[Constants.VIEWSTATE_PROFILE_URL] = myProfileUrl;

                mySiteHostUrl = Context.Items["SocialData$MySiteHostURL"] as string;

                ViewState[Constants.VIEWSTATE_MYSITE_URL] = mySiteHostUrl;

            }

            else

            {

                myProfileUrl = ViewState[Constants.VIEWSTATE_PROFILE_URL] as string;

                mySiteHostUrl = ViewState[Constants.VIEWSTATE_MYSITE_URL] as string;

            }

    

    

            if (string.IsNullOrEmpty(mySiteHostUrl))

            {

                // No MySite host, or user does not have rights to view profile page...

            placeHolderMySite.Visible = false;

 

            }

            else

            {

                // User has a MySite, show the link to it...

            placeHolderMySite.Visible = true;

            linkButtonMySite.OnClientClick = string.Format("STSNavigate2(event, '{0}');return false;", SPHttpUtility.EcmaScriptStringLiteralEncode(mySiteHostUrl));

            }

    

            if (string.IsNullOrEmpty(myProfileUrl))

            {

            // Use the SharePoint foundation profile page, since the MySite host is not available

            PostCacheSubstitutionText pt = new PostCacheSubstitutionText();

            pt.TextType = PostCacheSubstitutionTextType.UserId;

            pt.PrefixHtml = "<script type=\"text/javascript\">\n//<![CDATA[\nvar _spUserId=";

            pt.SuffixHtml = ";\n//]]>\n</script>";

            placeHolderUserID.Controls.Add(pt);

                string serverRelativeUrlFromUrl = this.ResolveClientUrl("~/_layouts/userdisp.aspx?Force=True&ID=");

            linkButtonEditProfile.OnClientClick = "GoToPage('" + SPHttpUtility.EcmaScriptStringLiteralEncode(serverRelativeUrlFromUrl) + "' + _spUserId);return false;";

            }

            else

            {

                // Use the MySite profile page...

            linkButtonEditProfile.OnClientClick = string.Format("STSNavigate2(event, '{0}');return false;", SPHttpUtility.EcmaScriptStringLiteralEncode(myProfileUrl));

            }

 

            // Login as another user

            string loginAsAnotherUserUrl = this.ResolveClientUrl("~/_layouts/closeConnection.aspx?loginasanotheruser=true");

            linkButtonLoginAsDifferentUser.OnClientClick = string.Format("LoginAsAnother('{0}', 0);return false;", SPHttpUtility.EcmaScriptStringLiteralEncode(loginAsAnotherUserUrl));

 

            // Sign out

            string signOutUrl = this.ResolveClientUrl("~/_layouts/SignOut.aspx");

            linkButtonLogOut.OnClientClick = "GoToPage('" + SPHttpUtility.EcmaScriptStringLiteralEncode(signOutUrl) + "');return false;";

 

        }

 

    }

}

Hopefully you find this useful, and can take it further if need be. Leave comments if you have any questions.

Tags: , ,

2 Responses to “Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 3”

  1. dr.j says:

    very well done, i would have like to seen the css that goes along with this.

  2. Bob says:

    Nice work. However I want to know how you make the div to be a dropdown. Thanks.

Leave a Reply