• images
  • 6:54 am
  • images
  • 2 Comments.

Fix for Your My Site profile not displaying the Organization Browser/chart in SharePoint 2013 + Inherit/override/modify SharePoint built in webpart

Have you ever wondered why your profile doesn’t show the Organization chart (or browser) when you see it yourself but shows up to other users when they visit your profile ? This behaviour is actually by design. The KB article from Microsoft clearly mentions this statement –

“This behavior is by design”

and suggests to use the Organization Browser webpart which is totally different. The Organization webpart that shows up when you view a user details page (mysite url/Person.aspx) looks very clean and many people and organizations like it. One interesting fact is that if you Edit “Person.aspx”, the organization chart shows up for your own profile too but disappears once you save the page and go back to View mode :-). So, the question is how to display it in all the scenarios. Unfortunately, there is no webpart property also which can help us achieve our requirement.

In this blog post, I will clearly explain how to achieve this requirement and also explain how to override/modify SharePoint out of the box webpart using reflection. To research this issue, let’s see how Microsoft has designed this webpart. The best way to do this is to open up reflector (my favourite :-) ) and check this webpart’s code. The Organization webpart is located in the dll called “Microsoft.SharePoint.Portal.dll” under the namespace “Microsoft.SharePoint.Portal.WebControls”. The class name is “ProfileManages”. The code from this class is shown below –

using Microsoft.Office.Server.Administration;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.Office.Server.Utilities;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Portal.WebControls.UserProfileHelper;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;

namespace Microsoft.SharePoint.Portal.WebControls
{
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    [SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel=true)]
    [SharePointPermission(SecurityAction.LinkDemand, ObjectModel=true)]
    [XmlRoot(Namespace="urn:schemas-microsoft-com:sharepoint:portal:orgchartwebpart")]
    public class ProfileManages : WebPartLoc, IDesignTimeHtmlProvider
    {
        private ProfilePropertyLoader m_objLoader;

        private UserProfile[] m_objManagers;

        private UserProfile[] m_objDirectReports;

        private UserProfile[] m_objPeers;

        private int m_CompatibilityLevel = 14;

        private int CompatibilityLevel
        {
            get
            {
                return this.m_CompatibilityLevel;
            }
            set
            {
                this.m_CompatibilityLevel = value;
            }
        }

        public ProfileManages()
        {
            CssRegistration.Register("Themable/portal.css");
            base.UseDefaultStyles = false;
            base.Load += new EventHandler(this.LoadControl);
        }

        private string GetPersonLink(string strPreferredName, string strAccountName, Guid guid, string idPrefix)
        {
            string str;
            string str1 = strAccountName;
            if (strPreferredName != null && strPreferredName.Length > 0)
            {
                str1 = strPreferredName;
            }
            str = (string.IsNullOrEmpty(strAccountName) ? UserProfileGlobal.GetUserProfileURL("?guid=", guid.ToString()) : UserProfileGlobal.GetUserProfileURL("?accountname=", strAccountName));
            string[] strArrays = new string[] { "<a class=\"ms-link ms-textSmall ms-subtleLink\" id=\"", HttpEncodingUtility.HtmlAttributeEncode(string.Concat(idPrefix, "_l")), "\" href=\"", SPHttpUtility.HtmlUrlAttributeEncode(str), "\"><b>", HttpUtility.HtmlEncode(str1), "</b></a>" };
            return string.Concat(strArrays);
        }

        internal static bool IsAssistant(UserProfile myProfile, UserProfile myReport)
        {
            string value = (string)myProfile["Assistant"].Value;
            string str = (string)myReport["AccountName"].Value;
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            return value.Equals(str, StringComparison.OrdinalIgnoreCase);
        }

        private void LoadControl(object sender, EventArgs e)
        {
            base.StopProcessingRequestIfNotNeeded();
            if (string.IsNullOrEmpty(this.Title))
            {
                this.Title = StringResourceManager.GetString(1946);
            }
            bool isRenderingDesignTime = DesignTimeHtmlProviderHelper.IsRenderingDesignTime;
        }

        [SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
        string Microsoft.SharePoint.WebControls.IDesignTimeHtmlProvider.GetDesignTimeHtml()
        {
            return base.GetNormalDesignTimeHtml();
        }

        [SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
        protected override void OnInit(EventArgs e)
        {
            bool flag;
            bool flag1;
            bool flag2;
            bool flag3;
            SPSite site = SPContext.Current.Site;
            if (site != null)
            {
                this.CompatibilityLevel = site.CompatibilityLevel;
            }
            if (!UserProfileApplicationProxy.IsAvailable(SPServiceContext.Current))
            {
                return;
            }
            this.m_objLoader = ProfilePropertyLoader.FindLoader(this.Page);
            IPersonalPage page = this.Page as IPersonalPage;
            if (this.m_objLoader != null && page != null)
            {
                flag = (base.DesignMode || base.WebPartManager.DisplayMode == WebPartManager.DesignDisplayMode ? true : base.WebPartManager.DisplayMode == WebPartManager.EditDisplayMode);
                bool flag4 = flag;
                if (!flag4 && page.ProfilePropertyLoader.IsSelf)
                {
                    this.Hidden = true;
                    return;
                }
                this.m_objLoader.ProfileLoaded.LoadOrganizationFromHierarchyCache(true);
                this.m_objManagers = this.m_objLoader.ProfileLoaded.GetManagersFromCache();
                flag1 = (this.m_objManagers == null ? false : (int)this.m_objManagers.Length > 0);
                bool flag5 = flag1;
                this.m_objDirectReports = this.m_objLoader.ProfileLoaded.GetDirectReportsFromCache();
                flag2 = (this.m_objDirectReports == null ? false : (int)this.m_objDirectReports.Length > 0);
                bool flag6 = flag2;
                if (!flag6)
                {
                    this.m_objPeers = this.m_objLoader.ProfileLoaded.GetPeersFromCache();
                }
                flag3 = (this.m_objPeers == null ? false : (int)this.m_objPeers.Length > 0);
                bool flag7 = flag3;
                if (!flag4 && !flag5 && !flag6 && !flag7)
                {
                    this.Hidden = true;
                }
            }
        }

        [SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
        protected override void OnPreRender(object sender, EventArgs e)
        {
            if (this.CompatibilityLevel >= 15)
            {
                WebPartTitleTranslator.TranslateTitle(this);
            }
        }

        private void RenderManagerRows(HtmlTextWriter writer, Colleague objLink, LocStringId locid, string prefix)
        {
            StringResourceManager.GetString(1962);
            writer.WriteLine("<TR>");
            writer.WriteLine("<TD valign=middle align=center height='16px' width='16px' style=\"font-family:Wingdings 3;font-size:8px\">");
            writer.Write("&#211;");
            writer.WriteLine("</TD>");
            writer.WriteLine("<TD CLASS=\"ms-announcementtitle\" WIDTH=\"100%\" style=\"vertical-align: middle\"><span class=\"ms-profilesection\">");
            writer.WriteLine(HttpUtility.HtmlEncode(StringResourceManager.GetString(locid)));
            writer.WriteLine("</span></TD></TR>");
            if (objLink == null)
            {
                writer.Write("<TR><td width=\"100%\" colspan=2><span>");
                writer.Write(HttpUtility.HtmlEncode(StringResourceManager.GetString(1966)));
                writer.WriteLine("</span></TD></TR>");
                return;
            }
            string value = (string)objLink.Profile["AccountName"].Value;
            string str = (string)objLink.Profile["PreferredName"].Value;
            string value1 = (string)objLink.Profile["WorkEmail"].Value;
            string str1 = (string)objLink.Profile["SPS-SipAddress"].Value;
            Guid d = objLink.Profile.ID;
            this.RenderOnePersonRow(writer, prefix, value1, str1, string.Empty, this.GetPersonLink(str, value, d, prefix));
        }

        private void RenderMultipleRows(HtmlTextWriter writer, UserProfile[] objProfiles, UserProfile objStartProfile, string prefix)
        {
            bool flag = objStartProfile == null;
            for (int i = 0; i < (int)objProfiles.Length; i++)
            {
                UserProfile userProfile = objProfiles[i];
                if (objStartProfile != null && objStartProfile.ID == userProfile.ID)
                {
                    flag = true;
                }
                if (flag)
                {
                    Guid d = userProfile.ID;
                    string value = (string)userProfile["AccountName"].Value;
                    string str = (string)userProfile["PreferredName"].Value;
                    string value1 = (string)userProfile["Title"].Value;
                    string str1 = (string)userProfile["WorkEmail"].Value;
                    string value2 = (string)userProfile["SPS-SipAddress"].Value;
                    this.RenderOnePersonRow(writer, string.Concat(prefix, i.ToString(CultureInfo.InvariantCulture)), str1, value2, value1, this.GetPersonLink(str, value, d, string.Concat(prefix, i.ToString(CultureInfo.InvariantCulture))));
                }
            }
        }

        private void RenderOnePersonRow(HtmlTextWriter writer, string strId, string strEmail, string strSipAddress, string strTitle, string strPersonLink)
        {
            if (strId == null)
            {
                strId = string.Empty;
            }
            if (strEmail == null)
            {
                strEmail = string.Empty;
            }
            writer.Write("<TR><TD width=\"100%\" colspan=2>");
            writer.Write("<table width=\"100%\" cellspacing=0 cellpadding=0><tr><td height='16px' width='16px' valign='middle' align='center'>");
            if (!strId.StartsWith("r", StringComparison.OrdinalIgnoreCase))
            {
                if (strId.StartsWith("m", StringComparison.OrdinalIgnoreCase))
                {
                    string str = StringResourceManager.GetString(1962);
                    writer.Write("<img border='0' src='{0}' alt='{1}'/>", ResourceFilePath.SharedImageUrl("reportsup.gif"), HttpUtility.HtmlAttributeEncode(str));
                }
            }
            else
            {
                writer.Write("<SPAN>");
                AdminUIGlobal.RenderIMPawn(writer, strId, strEmail, strSipAddress, true);
                writer.Write("</SPAN>");
            }
            writer.Write(string.Concat("</td><td align='", SiteInfo.GetLeftAlignValue(), "'"));
            if (!strId.StartsWith("r", StringComparison.OrdinalIgnoreCase))
            {
                writer.Write(" style='padding-top: 3px; padding-bottom: 3px'");
            }
            else
            {
                writer.Write(" style='padding-left: 21px; padding-top: 3px; padding-bottom: 3px' ");
            }
            writer.Write(">");
            writer.Write(strPersonLink);
            if (!string.IsNullOrEmpty(strTitle))
            {
                writer.Write("<span>&nbsp;&nbsp;<nobr>{0}</nobr></span>", HttpUtility.HtmlEncode(strTitle));
            }
            writer.Write("</td></tr></table>");
            writer.WriteLine("</TD></TR>");
        }

        private void RenderProfileAdditionalData(HtmlTextWriter writer, ProfileBase profile)
        {
            UserProfile userProfile = profile as UserProfile;
            if (userProfile != null)
            {
                string value = (string)userProfile["Title"].Value;
                if (!string.IsNullOrEmpty(value))
                {
                    writer.Write("<span class=\"ms_metadata \">&nbsp;&nbsp;<nobr>{0}</nobr></span>", HttpUtility.HtmlEncode(value));
                }
            }
        }

        private void RenderProfileUrl(HtmlTextWriter writer, ProfileBase profile)
        {
            UserProfile userProfile = profile as UserProfile;
            OrganizationProfile organizationProfile = profile as OrganizationProfile;
            if (userProfile != null)
            {
                writer.Write(this.GetPersonLink((string)userProfile["PreferredName"].Value, (string)userProfile["AccountName"].Value, userProfile.ID, string.Empty));
                return;
            }
            if (organizationProfile != null)
            {
                string[] str = new string[] { "<a id=\"", null, null, null, null, null, null };
                long recordId = organizationProfile.RecordId;
                str[1] = recordId.ToString();
                str[2] = "_2\" href=\"";
                str[3] = SPHttpUtility.HtmlUrlAttributeEncode(organizationProfile.PublicUrl.ToString());
                str[4] = "\">";
                str[5] = HttpUtility.HtmlEncode(organizationProfile.DisplayName);
                str[6] = "</a>";
                writer.Write(string.Concat(str));
            }
        }

        private void RenderSectionHeader(string sectionTitle, HtmlTextWriter writer)
        {
            writer.Write("<tr class='ms-profilehierarchysectionheader'><td height='16px' colspan=2><div class=\"ms-profilehierarchysectionheader\"><nobr>");
            SPHttpUtility.HtmlEncode(sectionTitle, writer);
            writer.WriteLine("</nobr></div></td></tr>");
        }

        private void RenderSubProfiles(HtmlTextWriter writer, ProfileBase[] objSubProfiles, bool bCurrentProfileIncluded)
        {
            writer.WriteLine("<tr><td width=\"8px;\">&nbsp;</td><td><table cellSpacing=0 cellPadding=0 width='100%'>");
            for (int i = 0; i < (int)objSubProfiles.Length; i++)
            {
                ProfileBase profileBase = objSubProfiles[i];
                writer.Write("<tr height='100%'><td><table height='100%' width='16' cellpadding=0 cellspacing=0 border='0'>");
                writer.Write("<tr height='9'><td valign='top' ");
                writer.Write("style='background-image: url(");
                writer.Write(SPHttpUtility.HtmlUrlAttributeEncode(ResourceFilePath.GetResourceFileUrl(ResourceFileContext.SharedImage, "hierbottom.gif")));
                writer.Write(")'></td></tr>");
                string str = StringResourceManager.GetString(1965);
                writer.Write(string.Concat("<tr height='1px'><td alt='", str, "' style='background-image: url("));
                if (!SiteInfo.IsUICultureRTL)
                {
                    writer.Write(SPHttpUtility.HtmlUrlAttributeEncode(ResourceFilePath.GetResourceFileUrl(ResourceFileContext.SharedImage, "hiertop.gif")));
                }
                else
                {
                    writer.Write(SPHttpUtility.HtmlUrlAttributeEncode(ResourceFilePath.GetResourceFileUrl(ResourceFileContext.SharedImage, "hiertoprtl.gif")));
                }
                writer.Write(")'/></tr><tr height='9'><td ");
                if (i < checked((int)objSubProfiles.Length - 1))
                {
                    writer.Write("style='background-image: url(");
                    writer.Write(SPHttpUtility.HtmlUrlAttributeEncode(ResourceFilePath.GetResourceFileUrl(ResourceFileContext.SharedImage, "hierbottom.gif")));
                    writer.Write(")'");
                }
                writer.Write("><IMG SRC='/_layouts/images/blank.gif' width=1 height=1 alt=''></td></tr></table></td>");
                if (!bCurrentProfileIncluded || i != 0)
                {
                    writer.Write(string.Concat("<td width='100%' class=\"ms-orgname\" align='", SiteInfo.GetLeftAlignValue(), "'>"));
                }
                else
                {
                    writer.Write(string.Concat("<td width='100%' class=\"ms-orgme ms-orgname\" align='", SiteInfo.GetLeftAlignValue(), "'>"));
                }
                this.RenderProfileUrl(writer, profileBase);
                this.RenderProfileAdditionalData(writer, profileBase);
                writer.Write("</td></tr>");
            }
            writer.Write("</table></td></tr>");
        }

        [SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
        protected override void RenderWebPart(HtmlTextWriter writer)
        {
            base.StopProcessingRequestIfNotNeeded();
            if (this.Hidden)
            {
                return;
            }
            if (!DesignTimeHtmlProviderHelper.IsRenderingDesignTime)
            {
                if (!UserProfileApplicationProxy.IsAvailable(SPServiceContext.Current))
                {
                    return;
                }
                if (this.m_objLoader != null && !this.m_objLoader.IsError && this.m_objLoader.LoadedProfile != null)
                {
                    this.RenderWebPartHierarchySection(writer);
                    this.RenderWebPartOrgBrowserLink(writer);
                }
                return;
            }
            writer.WriteLine("<table style=\"table-layout:fixed;word-wrap:break-word\" width=\"100%\">");
            if (this.ChromeType == PartChromeType.None)
            {
                this.RenderSectionHeader(this.Title, writer);
            }
            this.RenderManagerRows(writer, null, 1962, "m");
            writer.WriteLine("</table>");
        }

        private void RenderWebPartHierarchySection(HtmlTextWriter writer)
        {
            if (this.m_objLoader.Type == ProfileType.User)
            {
                writer.WriteLine("<table width=\"100%\" id=\"ReportingHierarchy\" cellspacing='0' cellpadding='0' border='0'>");
                UserProfile commonManager = this.m_objLoader.ProfileLoaded.GetCommonManager();
                if (this.m_objManagers != null && (int)this.m_objManagers.Length > 0)
                {
                    this.RenderMultipleRows(writer, this.m_objManagers, commonManager, "m");
                }
                List<UserProfile> userProfiles = new List<UserProfile>();
                if (this.m_objDirectReports != null)
                {
                    UserProfile[] mObjDirectReports = this.m_objDirectReports;
                    for (int i = 0; i < (int)mObjDirectReports.Length; i++)
                    {
                        UserProfile userProfile = mObjDirectReports[i];
                        userProfiles.Add(userProfile);
                    }
                }
                if (userProfiles.Count <= 0)
                {
                    List<UserProfile> userProfiles1 = new List<UserProfile>();
                    userProfiles1.Add(this.m_objLoader.ProfileLoaded);
                    if (this.m_objPeers != null)
                    {
                        UserProfile[] mObjPeers = this.m_objPeers;
                        for (int j = 0; j < (int)mObjPeers.Length; j++)
                        {
                            UserProfile userProfile1 = mObjPeers[j];
                            userProfiles1.Add(userProfile1);
                        }
                    }
                    this.RenderSubProfiles(writer, userProfiles1.ToArray(), true);
                }
                else
                {
                    string str = StringResourceManager.GetString(1963);
                    writer.Write("\n<tr height=3><td></td></tr>\n");
                    writer.Write("<TR class=\"ms-orgme\"><TD width=\"100%\" colspan=2>");
                    writer.Write("<table width=\"100%\" cellspacing=0 cellpadding=0 ><tr><td height='16px' width='16px' valign='middle' align='center'>");
                    string[] strArrays = new string[] { "<img src=\"", SPHttpUtility.HtmlUrlAttributeEncode(ResourceFilePath.GetResourceFileUrl(ResourceFileContext.SharedImage, "reportsup.gif")), "\" alt=\"", HttpUtility.HtmlEncode(str), "\">" };
                    writer.Write(string.Concat(strArrays));
                    writer.Write("</TD>");
                    writer.Write(string.Concat("<td class=\"ms-orgme\" style='padding-left:2px;padding-right:2px;padding-bottom:3px;padding-top:3px;font-weight:bold' class='ms-textSmall ms-subtleLink' align='", SiteInfo.GetLeftAlignValue(), "'>"));
                    writer.Write(HttpUtility.HtmlEncode((string)this.m_objLoader.ProfileLoaded["PreferredName"].Value));
                    string value = (string)this.m_objLoader.ProfileLoaded["Title"].Value;
                    if (!string.IsNullOrEmpty(value))
                    {
                        writer.Write("<span class='ms_metadata'>&nbsp;&nbsp;<nobr>{0}</nobr></span>", HttpUtility.HtmlEncode(value));
                    }
                    writer.WriteLine("</TD></TR></TABLE></td></tr>");
                    this.RenderSubProfiles(writer, userProfiles.ToArray(), false);
                }
                writer.WriteLine("</table>");
            }
        }

        private void RenderWebPartOrgBrowserLink(HtmlTextWriter writer)
        {
            string originalString = this.m_objLoader.LoadedProfile.PublicOrganizationViewUrl.OriginalString;
            if (this.m_objLoader.Type == ProfileType.User)
            {
                originalString = this.m_objLoader.ProfileLoaded.PublicOrganizationViewUrl.OriginalString;
            }
            if (this.CompatibilityLevel < 15)
            {
                string str = StringResourceManager.GetString(1959);
                writer.WriteLine(string.Concat("<table width=\"100%\"><tr><td align='", SiteInfo.GetLeftAlignValue(), "'>"));
                writer.Write("<span style=\"height:16px;width:16px;position:relative;display:inline-block;overflow:hidden;\"><img src=\"/_layouts/15/images/mossfgimg.png?rev=23\" alt=\"\" style=\"left:-0px !important;top:-116px !important;position:absolute;\"  /></span>");
                string[] strArrays = new string[] { " <a href=\"", SPHttpUtility.HtmlUrlAttributeEncode(originalString), "\">", HttpUtility.HtmlEncode(str), "</a>" };
                writer.Write(string.Concat(strArrays));
                writer.WriteLine("</td></tr></table>");
                return;
            }
            string str1 = StringResourceManager.GetString(1960);
            writer.Write("<div class=\"ms-profile-organizationLink\">");
            string[] strArrays1 = new string[] { "<a class=\"ms-commandLink\" href=\"", SPHttpUtility.HtmlUrlAttributeEncode(originalString), "\" id=\"orgBrowserLink_", this.ClientID, "\">", HttpUtility.HtmlEncode(str1), "</a>" };
            writer.Write(string.Concat(strArrays1));
            writer.Write("</div>");
        }

        [SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
        public override bool RequiresWebPartClientScript()
        {
            return false;
        }
    }
}

If you analyze the class properly, you will see many scenarios where there are specific checks to prevent display of the webpart if the user is viewing his own profile. Check the following glaring line for example in the “OnInit” method –

if (!flag4 &amp;&amp; page.ProfilePropertyLoader.IsSelf)
{
this.Hidden = true;
return;
}

The above line is just one of the many checks that prevents its display for the logged-in user while visiting the self profile. Now after seeing the code it is very clear why the webpart is behaving in this manner.

To overcome this problem, let us build our own webpart which will inherit “ProfileManages” class and use reflection to override all the code which is causing all the trouble.
Following are the steps to do this –

1) Create an empty SharePoint project in VS2012 (You may use an existing project also).

2) Add a New item -> Webpart (not visula webpart).

3) In the project references, reference the following dlls –

Microsoft.Office.Server.dll
Microsoft.Office.Server.Search.dll
Microsoft.Office.Server.UserProfiles.dll
Microsoft.SharePoint.portal.dll

4) In the webpart class, type the following code –

using System;
using System.ComponentModel;
using System.Web;
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.Portal.WebControls;
using Microsoft.SharePoint.Portal;
using System.Reflection;
using Microsoft.Office.Server.UserProfiles;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Administration;
using Microsoft.Office.Server.Administration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace "Your namespace"
{
    [ToolboxItemAttribute(false)]
    public class Organization : ProfileManages
    {

        private int m_CompatibilityLevel = 14;
        private ProfilePropertyLoader m_objLoader;
        private UserProfile[] m_objManagers;
        private UserProfile[] m_objDirectReports;
        private UserProfile[] m_objPeers;

        private int CompatibilityLevel
        {
            get
            {
                return this.m_CompatibilityLevel;
            }
            set
            {
                this.m_CompatibilityLevel = value;
            }
        }       

        protected override void OnInit(EventArgs e)
        {
            
            base.OnInit(e);            
            bool flag1;
            bool flag2;
            bool flag3;
            SPSite site = SPContext.Current.Site;

            this.Hidden = false;

            if (site != null)
            {
                this.CompatibilityLevel = site.CompatibilityLevel;
            }

            if (!IsUserProfileApplicationProxyAvailable())
             {
                 return;
             } 
            this.m_objLoader = ProfilePropertyLoader.FindLoader(this.Page);
            IPersonalPage page = this.Page as IPersonalPage;
            if (this.m_objLoader != null && page != null)
            {
                MethodInfo method = this.m_objLoader.ProfileLoaded.GetType().GetMethod("LoadOrganizationFromHierarchyCache", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(bool) }, null);
                method.Invoke(this.m_objLoader.ProfileLoaded, BindingFlags.InvokeMethod, null, new object[] { true }, CultureInfo.CurrentCulture);          
                
                MethodInfo method2 = this.m_objLoader.ProfileLoaded.GetType().GetMethod("GetManagersFromCache", BindingFlags.NonPublic | BindingFlags.Instance);
                this.m_objManagers = (UserProfile[])method2.Invoke(this.m_objLoader.ProfileLoaded, null);

                flag1 = (this.m_objManagers == null ? false : (int)this.m_objManagers.Length > 0);
                bool flag5 = flag1;               
                MethodInfo method3 = this.m_objLoader.ProfileLoaded.GetType().GetMethod("GetDirectReportsFromCache", BindingFlags.NonPublic | BindingFlags.Instance);
                this.m_objDirectReports = (UserProfile[])method3.Invoke(this.m_objLoader.ProfileLoaded, null);

                flag2 = (this.m_objDirectReports == null ? false : (int)this.m_objDirectReports.Length > 0);
                bool flag6 = flag2;
                if (!flag6)
                {
                    MethodInfo method4 = this.m_objLoader.ProfileLoaded.GetType().GetMethod("GetPeersFromCache", BindingFlags.NonPublic | BindingFlags.Instance);
                    this.m_objPeers = (UserProfile[])method4.Invoke(this.m_objLoader.ProfileLoaded, null);
                }
                flag3 = (this.m_objPeers == null ? false : (int)this.m_objPeers.Length > 0);
                bool flag7 = flag3;
                if (!flag5 && !flag6 && !flag7)
                {
                    this.Hidden = true;
                }
            }
        }

        protected override void CreateChildControls()
        {        
            
        }     
       

        protected override void RenderWebPart(HtmlTextWriter writer)
        {
            if (!IsUserProfileApplicationProxyAvailable())
            {
                return;
            }

            if (this.m_objLoader != null && !this.m_objLoader.IsError && this.m_objLoader.LoadedProfile != null)
            {
                this.RenderWebPartHierarchySection(writer);
                MethodInfo dynMethod2 = this.GetType().BaseType.GetMethod("RenderWebPartOrgBrowserLink", BindingFlags.NonPublic | BindingFlags.Instance);
                dynMethod2.Invoke(this, new object[] { writer });
            }

            writer.WriteLine("<table style=\"table-layout:fixed;word-wrap:break-word\" width=\"100%\">");
            if (this.ChromeType == PartChromeType.None)
            {
                this.RenderSectionHeader(this.Title, writer);
            }
            //MethodInfo dynMethod3 = this.GetType().BaseType.GetMethod("RenderManagerRows", BindingFlags.NonPublic | BindingFlags.Instance);
            //dynMethod3.Invoke(this, new object[] { writer, null, 1962, "m" });
            //RenderManagerRows(writer, null, 1962, "m");
            writer.WriteLine("</table>");  
        }

        private void RenderManagerRows(HtmlTextWriter writer, Colleague objLink, int locid, string prefix)
        {
            GetStringResMgrString(1962); //StringResourceManager.GetString(1962);
            writer.WriteLine("<TR>");
            writer.WriteLine("<TD valign=middle align=center height='16px' width='16px' style=\"font-family:Wingdings 3;font-size:8px\">");
            writer.Write("&#211;");
            writer.WriteLine("</TD>");
            writer.WriteLine("<TD CLASS=\"ms-announcementtitle\" WIDTH=\"100%\" style=\"vertical-align: middle\"><span class=\"ms-profilesection\">");
            writer.WriteLine(HttpUtility.HtmlEncode(GetStringResMgrString(locid)));
            writer.WriteLine("</span></TD></TR>");
            if (objLink == null)
            {
                writer.Write("<TR><td width=\"100%\" colspan=2><span>");
                writer.Write(HttpUtility.HtmlEncode(GetStringResMgrString(1966)));
                writer.WriteLine("</span></TD></TR>");
                return;
            }
            string value = (string)objLink.Profile["AccountName"].Value;
            string str = (string)objLink.Profile["PreferredName"].Value;
            string value1 = (string)objLink.Profile["WorkEmail"].Value;
            string str1 = (string)objLink.Profile["SPS-SipAddress"].Value;
            Guid d = objLink.Profile.ID;
            MethodInfo RenderOnePersonRowMethod = this.GetType().BaseType.GetMethod("RenderOnePersonRow", BindingFlags.NonPublic | BindingFlags.Instance);
            RenderOnePersonRowMethod.Invoke(this, new object[] { writer, prefix, value1, str1, string.Empty, GetPersonLink(str, value, d, prefix) });
            //this.RenderOnePersonRow(writer, prefix, value1, str1, string.Empty, GetPersonLink(str, value, d, prefix));
        }

        private string GetPersonLink(string strPreferredName, string strAccountName, Guid guid, string idPrefix)
        {
            string getPersonLink = "";
            MethodInfo GetPersonLinkMethod = this.GetType().BaseType.GetMethod("GetPersonLink", BindingFlags.NonPublic | BindingFlags.Instance);
            getPersonLink = (string)GetPersonLinkMethod.Invoke(this, new object[] { strPreferredName, strAccountName, guid, idPrefix });
            return getPersonLink;
        }

        private void RenderWebPartHierarchySection(HtmlTextWriter writer)
        {          
                writer.WriteLine("<table width=\"100%\" id=\"ReportingHierarchy\" cellspacing='0' cellpadding='0' border='0'>");
                UserProfile commonManager = this.m_objLoader.ProfileLoaded.GetCommonManager();
                if (this.m_objManagers != null && (int)this.m_objManagers.Length > 0)
                {
                  /*  MethodInfo RenderMultipleRowsMethod = this.GetType().BaseType.GetMethod("RenderMultipleRows", BindingFlags.NonPublic | BindingFlags.Instance); 
                    RenderMultipleRowsMethod.Invoke(this, new object[] { writer, this.m_objManagers, commonManager, "m" });  */
                    RenderMultipleRows(writer, this.m_objManagers, commonManager, "m");
                }

                List<UserProfile> userProfiles = new List<UserProfile>();
                if (this.m_objDirectReports != null)
                {
                    UserProfile[] mObjDirectReports = this.m_objDirectReports;
                    for (int i = 0; i < (int)mObjDirectReports.Length; i++)
                    {
                        UserProfile userProfile = mObjDirectReports[i];
                        userProfiles.Add(userProfile);
                    }
                }
                if (userProfiles.Count <= 0)
                {
                    List<UserProfile> userProfiles1 = new List<UserProfile>();
                    userProfiles1.Add(this.m_objLoader.ProfileLoaded);
                    if (this.m_objPeers != null)
                    {
                        UserProfile[] mObjPeers = this.m_objPeers;
                        for (int j = 0; j < (int)mObjPeers.Length; j++)
                        {
                            UserProfile userProfile1 = mObjPeers[j];
                            userProfiles1.Add(userProfile1);
                        }
                    }                   
                    MethodInfo RenderSubProfilesMethod = this.GetType().BaseType.GetMethod("RenderSubProfiles", BindingFlags.NonPublic | BindingFlags.Instance);
                    RenderSubProfilesMethod.Invoke(this, new object[] { writer, userProfiles1.ToArray(), true });
                }
                else
                {
                    string str = GetStringResMgrString(1963);
                    writer.Write("\n<tr height=3><td></td></tr>\n");
                    writer.Write("<TR class=\"ms-orgme\"><TD width=\"100%\" colspan=2>");
                    writer.Write("<table width=\"100%\" cellspacing=0 cellpadding=0 ><tr><td height='16px' width='16px' valign='middle' align='center'>");
                    string[] strArrays = new string[] { "<img src=\"", SPHttpUtility.HtmlUrlAttributeEncode(ResourceFilePath.GetResourceFileUrl(ResourceFileContext.SharedImage, "reportsup.gif")), "\" alt=\"", HttpUtility.HtmlEncode(str), "\">" };
                    writer.Write(string.Concat(strArrays));
                    writer.Write("</TD>");
                    writer.Write(string.Concat("<td class=\"ms-orgme\" style='padding-left:2px;padding-right:2px;padding-bottom:3px;padding-top:3px;font-weight:bold' class='ms-textSmall ms-subtleLink' align='", SiteInfo.GetLeftAlignValue(), "'>"));
                    writer.Write(HttpUtility.HtmlEncode((string)this.m_objLoader.ProfileLoaded["PreferredName"].Value));
                    string value = (string)this.m_objLoader.ProfileLoaded["Title"].Value;
                    if (!string.IsNullOrEmpty(value))
                    {
                        writer.Write("<span class='ms_metadata'>&nbsp;&nbsp;<nobr>{0}</nobr></span>", HttpUtility.HtmlEncode(value));
                    }
                    writer.WriteLine("</TD></TR></TABLE></td></tr>");
                    
                    MethodInfo RenderSubProfilesMethod = this.GetType().BaseType.GetMethod("RenderSubProfiles", BindingFlags.NonPublic | BindingFlags.Instance);
                    RenderSubProfilesMethod.Invoke(this, new object[] { writer, userProfiles.ToArray(), false });                    
                }
                writer.WriteLine("</table>");            
        }

        private void RenderSectionHeader(string sectionTitle, HtmlTextWriter writer)
        {
            writer.Write("<tr class='ms-profilehierarchysectionheader'><td height='16px' colspan=2><div class=\"ms-profilehierarchysectionheader\"><nobr>");
            SPHttpUtility.HtmlEncode(sectionTitle, writer);
            writer.WriteLine("</nobr></div></td></tr>");
        }

        private void RenderMultipleRows(HtmlTextWriter writer, UserProfile[] objProfiles, UserProfile objStartProfile, string prefix)
        {
            bool flag = objStartProfile == null;
            for (int i = 0; i < (int)objProfiles.Length; i++)
            {
                UserProfile userProfile = objProfiles[i];
                if (objStartProfile != null ) //&& objStartProfile.ID == userProfile.ID)
                {
                    flag = true;
                }
                if (flag)
                {
                    Guid d = userProfile.ID;
                    string value = (string)userProfile["AccountName"].Value;
                    string str = (string)userProfile["PreferredName"].Value;
                    string value1 = (string)userProfile["Title"].Value;
                    string str1 = (string)userProfile["WorkEmail"].Value;
                    string value2 = (string)userProfile["SPS-SipAddress"].Value;

                    MethodInfo method = this.m_objLoader.ProfileLoaded.GetType().GetMethod("GetDirectReportsFromCache", BindingFlags.NonPublic | BindingFlags.Instance);
                    this.m_objDirectReports = (UserProfile[])method.Invoke(this.m_objLoader.ProfileLoaded, null);

                    MethodInfo dynMethod = this.GetType().BaseType.GetMethod("RenderOnePersonRow", BindingFlags.NonPublic | BindingFlags.Instance);
                    dynMethod.Invoke(this, new object[] { writer, string.Concat(prefix, i.ToString(CultureInfo.InvariantCulture)), str1, value2, value1, this.GetPersonLink(str, value, d, string.Concat(prefix, i.ToString(CultureInfo.InvariantCulture))) });
                                       
                   // this.RenderOnePersonRow(writer, string.Concat(prefix, i.ToString(CultureInfo.InvariantCulture)), str1, value2, value1, this.GetPersonLink(str, value, d, string.Concat(prefix, i.ToString(CultureInfo.InvariantCulture))));
                }
            }
        }

        private string GetStringResMgrString(int id)
        {            
            var stringResourceManagerType = Type.GetType("Microsoft.SharePoint.Portal.WebControls.StringResourceManager, Microsoft.Office.Server.Search, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
            var getStringProperty = stringResourceManagerType.GetMethod("GetString", AllBindings);
            object[] parameters = { id };
            return getStringProperty.Invoke(null, parameters) as string;
        }

        private static BindingFlags AllBindings
        {
            get
            {
                return BindingFlags.CreateInstance |
                    BindingFlags.FlattenHierarchy |
                    BindingFlags.GetField |
                    BindingFlags.GetProperty |
                    BindingFlags.IgnoreCase |
                    BindingFlags.Instance |
                    BindingFlags.InvokeMethod |
                    BindingFlags.NonPublic |
                    BindingFlags.Public |
                    BindingFlags.SetField |
                    BindingFlags.SetProperty |
                    BindingFlags.Static;
            }
        }

        private bool IsUserProfileApplicationProxyAvailable()
        {
            bool IsUPSAAvailable = true;
            var upaProxyType = Type.GetType("Microsoft.Office.Server.Administration.UserProfileApplicationProxy, Microsoft.Office.Server.UserProfiles, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
            var userProfileManager = new UserProfileManager(SPServiceContext.Current, false, false);
            var prop = userProfileManager.GetType().GetProperty("UserProfileApplicationProxy", AllBindings);
            var proxy = prop.GetValue(userProfileManager, null);
            var upaProxyIsAvailableProperty = upaProxyType.GetMethod("IsAvailable", AllBindings);
            object[] parameters = { SPServiceContext.Current };
            Object ret = upaProxyIsAvailableProperty.Invoke(proxy, parameters);
            if (ret != null)
                IsUPSAAvailable = (bool)ret;
            return IsUPSAAvailable;
        }

    }
}

5. Create your .dwp file (older .webpart file) :

To do this, add a file with the same name as your webpart in the location of your ‘.webpart’ file but give it an extension of ‘.dwp’. (I mean if your webpart file is Organization.webpart, create and add Organization.dwp to the same place in your project).

Copy and paste the following code into your .dwp file and update all the attributes from your .webpart file.

<?xml version="1.0" encoding="utf-8"?>
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">
  <Assembly>$SharePoint.Project.AssemblyFullName$,Version=1.0.0.0,Culture=Neutral,PublicToken="Your assembly publickeytoken"</Assembly>
  <TypeName>Copy from .webpart file</TypeName>
  <Title>Copy from .webpart file</Title>
  <Description>Copy from .webpart file</Description>
</WebPart>

How to find publickeyttoken : Go to the location – C:\Windows\Microsoft.NET\assembly\GAC_MSIL. Find the folder for your assembly (You may need to deploy your project to see your assembly there). Go inside that folder. There you will find another folder similar to “v4.0_15.0.0.0__71e9bce111e9429c”. The last part of that folder name is your publickeytoken.

6. Build and Deploy your project.

7. Navigate to MySite host. Go to Site Settings -> Webparts and upload your Organization.dwp file.

8. Edit Person.aspx inside your MySite host and add our Organization webpart. Save the page ad see your webpart :-)

2 Comments

mrbigonline

January 30, 2014 2:58 pm Reply

Aren’t you making it too difficult? The old Organization chart webpart still exists. Put it on the My Profile page. Set it to HTML mode.

Almost the same layout as the 2013 org chart webpart….

westerdaled

July 3, 2014 5:03 pm Reply

This is really good post. It is a pity this has to be done in a web part albeit a fairly simple one . Microsoft should have has allowed this in PowerShell with a profilemanager object

Leave a Comment