Fix for Visual Studio 2012 crash on publish of SharePoint wsp

Have you ever wondered why VS2012 sometimes crashes when you try to publish a wsp? I faced this issue several times and then spent some time to analyze the cause.

I found that if you donot specify a Site Url in the SP Project properties and try to publish a wsp, VS will simply crash and restart. To solve the problem, simply do the following -

1) In the VS Solution explorer window, select the SharePoint project and click F4 button (project properties).

2) In the project properties section, enter a valid Site Url and save the project. (Then the project properties will show “Online” instead of “Cannot connect to SharePoint farm”.)

Publish the wsp again. It works without crashing :-) …Whoa!!!

VS Bug

 

REST API Security Trimming SharePoint 2013

REST API is a great means of interacting with data in SharePoint 2013 on-premise and online.  It was introduced in SP2010 and is greatly enhanced in SP2013. However, the results in REST queries are not always security trimmed.

Let us consider a simple scenario : We want to display the list of subsites which are accessible to the logged in user using Javascript. A normal REST query for this scenario will be like this -

http://site/_api/web/webs/?$select=title

However, to your surprise you will find that the results returned by this query are not security trimmed. In other words, it will display all the subsites irrespective of whether the user can access it or not. This requirement can be done using Client object model. But what if you want to access data from a different site collection? CSOM will not help in that case. We have to use REST for that scenario. So, how do we proceed ?

Fortunately, there is a way. Simply use the following query :


http://site/_api/web/webs/?$select=title,effectivebasepermissions&$filter=effectivebasepermissions/high%20gt%2032

This query will only return the list of subsites which are accessible to current user :-) .

Explanation :

As you can see, the trick is the filter “effectivebasepermissions” which filters the results. If you are curious about the number 32, have a look at the following links to understand the permission numbers -

http://jamestsai.net/Blog/post/Understand-SharePoint-Permissions-Part-2-Check-SharePoint-usergroup-permissions-with-Permissions-web-service-and-JavaScript.aspx

http://jamestsai.net/Blog/post/Understand-SharePoint-Permissions—Part-1-SPBasePermissions-in-Hex2c-Decimal-and-Binary—The-Basics.aspx

Then, fire a query like this -


http://site/_api/web/roledefinitions

This will return you the list of available role definitons and you can analyze that for all the roles having high value < 32, user cannot access the web. This is how we get the lucky number "32".

<?xml version="1.0" encoding="utf-8" ?> 
- <feed xml:base="https://yourcompany.com/sites/projects/_api/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
  <id>ae4644c5-38a4-4a34-836e-5defb670188b</id> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741829)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741829)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">2147483647</d:High> 
  <d:Low m:type="Edm.Int64">4294967295</d:Low> 
  </d:BasePermissions>
  <d:Description>Has full control.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741829</d:Id> 
  <d:Name>Full Control</d:Name> 
  <d:Order m:type="Edm.Int32">1</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">5</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741828)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741828)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">432</d:High> 
  <d:Low m:type="Edm.Int64">1012866047</d:Low> 
  </d:BasePermissions>
  <d:Description>Can view, add, update, delete, approve, and customize.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741828</d:Id> 
  <d:Name>Design</d:Name> 
  <d:Order m:type="Edm.Int32">32</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">4</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741830)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741830)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">432</d:High> 
  <d:Low m:type="Edm.Int64">1011030767</d:Low> 
  </d:BasePermissions>
  <d:Description>Can add, edit and delete lists; can view, add, update and delete list items and documents.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741830</d:Id> 
  <d:Name>Edit</d:Name> 
  <d:Order m:type="Edm.Int32">48</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">6</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741827)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741827)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">432</d:High> 
  <d:Low m:type="Edm.Int64">1011028719</d:Low> 
  </d:BasePermissions>
  <d:Description>Can view, add, update, and delete list items and documents.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741827</d:Id> 
  <d:Name>Contribute</d:Name> 
  <d:Order m:type="Edm.Int32">64</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">3</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741826)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741826)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">176</d:High> 
  <d:Low m:type="Edm.Int64">138612833</d:Low> 
  </d:BasePermissions>
  <d:Description>Can view pages and list items and download documents.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741826</d:Id> 
  <d:Name>Read</d:Name> 
  <d:Order m:type="Edm.Int32">128</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">2</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741825)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741825)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">16</d:High> 
  <d:Low m:type="Edm.Int64">134283264</d:Low> 
  </d:BasePermissions>
  <d:Description>Can view specific lists, document libraries, list items, folders, or documents when given permissions.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">true</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741825</d:Id> 
  <d:Name>Limited Access</d:Name> 
  <d:Order m:type="Edm.Int32">160</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">1</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741924)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741924)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">176</d:High> 
  <d:Low m:type="Edm.Int64">138612801</d:Low> 
  </d:BasePermissions>
  <d:Description>Can view pages, list items, and documents. Document types with server-side file handlers can be viewed in the browser but not downloaded.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741924</d:Id> 
  <d:Name>View Only</d:Name> 
  <d:Order m:type="Edm.Int32">2147483647</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">0</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741925)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741925)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">432</d:High> 
  <d:Low m:type="Edm.Int64">1011028991</d:Low> 
  </d:BasePermissions>
  <d:Description>Can edit and approve pages, list items, and documents.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741925</d:Id> 
  <d:Name>Approve</d:Name> 
  <d:Order m:type="Edm.Int32">2147483647</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">0</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741926)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741926)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">1073742320</d:High> 
  <d:Low m:type="Edm.Int64">2129075183</d:Low> 
  </d:BasePermissions>
  <d:Description>Can create sites and edit pages, list items, and documents.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741926</d:Id> 
  <d:Name>Manage Hierarchy</d:Name> 
  <d:Order m:type="Edm.Int32">2147483647</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">0</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741927)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741927)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">0</d:High> 
  <d:Low m:type="Edm.Int64">196641</d:Low> 
  </d:BasePermissions>
  <d:Description>Can view pages and documents, but cannot view historical versions or user permissions.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741927</d:Id> 
  <d:Name>Restricted Read</d:Name> 
  <d:Order m:type="Edm.Int32">2147483647</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">0</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
- <entry>
  <id>https://yourcompany.com/sites/projects/_api/Web/RoleDefinitions(1073741928)</id> 
  <category term="SP.RoleDefinition" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
  <link rel="edit" href="Web/RoleDefinitions(1073741928)" /> 
  <title /> 
  <updated>2013-08-18T17:42:37Z</updated> 
- <author>
  <name /> 
  </author>
- <content type="application/xml">
- <m:properties>
- <d:BasePermissions m:type="SP.BasePermissions">
  <d:High m:type="Edm.Int64">32</d:High> 
  <d:Low m:type="Edm.Int64">65536</d:Low> 
  </d:BasePermissions>
  <d:Description>Can open lists and folders, and use remote interfaces.</d:Description> 
  <d:Hidden m:type="Edm.Boolean">false</d:Hidden> 
  <d:Id m:type="Edm.Int32">1073741928</d:Id> 
  <d:Name>Restricted Interfaces for Translation</d:Name> 
  <d:Order m:type="Edm.Int32">2147483647</d:Order> 
  <d:RoleTypeKind m:type="Edm.Int32">0</d:RoleTypeKind> 
  </m:properties>
  </content>
  </entry>
  </feed>

Hope it helps :-)

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 :-)

Powershell to create and reuse Managed Navigation for multiple sites in SharePoint 2013

As promised earlier, below is a powershell script to create managed navigation in SharePoint 2013 using powershell. Before reading below, I would strongly suggest to read my previous post on managed navigation here

Add-PSSnapin Microsoft.SharePoint.Powershell

#change these variables based on environment
$siteName = "Site url" 
$siteSearchName = "Search site url" 
$termStoreName = “Managed Metadata Service”
$termGroupName = “My Navigation”
$termsetName = "MyNavigationTermset"
$termsetSearchName = "MyNavigationTermset Search"
$appendUrl = "Site url"

function CreateTerm( $parent, $name, $url )  
 {  
  Write-Host "Adding term $name to parent $parent.Name"  
   $term = $parent.CreateTerm("$name", 1033)  
  $term.IsAvailableForTagging = $true    
  $newUrl = $url
  if(!$url.ToLower().Contains("http"))
  {  
  # Logic to append site url to relative path to create complete url which is needed for Simple Link Navigation
    $newUrl = $appendUrl + $url
  }
  $term.SetLocalCustomProperty("_Sys_Nav_SimpleLinkUrl", $newUrl)   
  return $term  
 } 

# Create termgroup and termset for My Site

$site = Get-SPSite -Identity $siteName
$session = Get-SPTaxonomySession -Site $siteName
$termStore = $session.TermStores[$termStoreName]
$group = $termstore.CreateGroup($termGroupName)
$group.Description = "Term Group description"
$termStore.CommitAll()

Write-Host "TermGroup - $termGroupName created successfully"  

$termsetName = "Name of your navigation termset"
$termSet = $group.CreateTermSet($termsetName,1033)
$termSet.Description = “Navigation TermSet description”
$termSet.IsAvailableForTagging = $false
$termSet.IsOpenForTermCreation = $false
$navigationSet = $group.TermSets[$termsetName]
$navigationSet.SetCustomProperty("_Sys_Nav_IsNavigationTermSet", "True")
$termStore.CommitAll()

Write-Host "TermSet - $termsetName created successfully"  

# create terms for My site

$wwrTerm = CreateTerm $termSet “WHO WE ARE” "/who"
$wavTerm = CreateTerm $termSet “WORKING AT OUR COMPANY” "/working"
$wynTerm = CreateTerm $termSet “ABOUT US” "/what"

$termStore.CommitAll()

$termSet.CustomSortOrder = $wwrTerm.id.ToString()+":"+$wavTerm.id.ToString()+":"+$wynTerm.id.ToString()

# create sub terms for My site

$term1 = CreateTerm $wwrTerm "Company" "/who/company"
$term2 = CreateTerm $wwrTerm "Organization" "/who/organization"
$term3 = CreateTerm $wwrTerm "Products" "/who/products"

$term4 = CreateTerm $wavTerm "Perks" "/working/perks"
$term5 = CreateTerm $wavTerm "Recognition" "/working/recognition"
$term6 = CreateTerm $wavTerm "HR Info" "/who/organization/hr"

$term7 = CreateTerm $wynTerm "Resources and Services" "/what/resources/"
$term8 = CreateTerm $wynTerm "Policies" "/what/policies"
$term9 = CreateTerm $wynTerm "Contact Us" "/what/contact"

$wwrTerm.CustomSortOrder = $term1.id.ToString() +":"+ $term2.id.ToString() +":"+ $term3.id.ToString()
$wavTerm.CustomSortOrder = $term4.id.ToString() +":"+ $term5.id.ToString() +":"+ $term6.id.ToString()
$wynTerm.CustomSortOrder = $term7.id.ToString() +":"+ $term8.id.ToString() +":"+ $term9.id.ToString()
$termStore.CommitAll()

Write-Host "Terms for TermSet - $termsetName created successfully"  

# create terms for My Site Search

$termSet = $group.CreateTermSet($termsetSearchName,1033)
$termSet.Description = “Navigation TermSet for Search site”
$termSet.IsAvailableForTagging = $false
$termSet.IsOpenForTermCreation = $false
$navigationSet = $group.TermSets[$termsetName]
$navigationSet.SetCustomProperty("_Sys_Nav_IsNavigationTermSet", "True")
$termStore.CommitAll()

Write-Host "TermSet - $termsetSearchName created successfully"  

$wwrTermSearch = $termSet.ReuseTerm($wwrTerm,$true);
$wavTermSearch = $termSet.ReuseTerm($wavTerm,$true);
$wynTermSearch = $termSet.ReuseTerm($wynTerm,$true);

$termSet.CustomSortOrder = $wwrTerm.id.ToString()+":"+$wavTerm.id.ToString()+":"+$wynTerm.id.ToString()

$termStore.CommitAll()

$wwrTermSearch.CustomSortOrder = $term1.id.ToString() +":"+ $term2.id.ToString() +":"+ $term3.id.ToString()
$wavTermSearch.CustomSortOrder = $term4.id.ToString() +":"+ $term5.id.ToString() +":"+ $term6.id.ToString()
$wynTermSearch.CustomSortOrder = $term7.id.ToString() +":"+ $term8.id.ToString() +":"+ $term9.id.ToString()
$termStore.CommitAll()

Write-Host "Terms for TermSet - $termsetName created successfully"

The script above creates a navigation termset with some dummy terms for “My Site” and reuses the same terms for “My Site Search” so that both the sites can have the same managed navigation. This script also takes care of custom sort order for parent and child level terms. Also, note that there is a concept of “append url” which helps in creating the full url before assigning it to the term.

Create, update and order user profile properties using Powershell in Sharepoint 2013

User profile properties can be created and managed using the graphical interface inside SharePoint central admin.(Central Admin -> Manage Service Applications -> User Profile Service Application -> Manage User Properties). But in a real production scenario where lot of user profile properties need to be created and ordered, the GUI way becomes extremely tedious and timetaking. But, don’t worry, we can automate everything using powershell :-) .

Below is the powershell script which creates and updates (if prop already exists) the different user profile properties and orders them also by reading from a XML file.

#Script to find all employees/contractors who roll up to a manager and add their usernames to the manager's colleague list in SharePoint 
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server")  
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles")  
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles.UserProfileManager")  
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")  

$filePath = "Path to XML file containing user profile props";
$siteName = "Site url";

clear-host
#add sharepoint cmdlets
if ( (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{    
      Add-PsSnapin Microsoft.SharePoint.PowerShell
}

[System.Xml.XmlDocument] $XmlDoc = new-object System.Xml.XmlDocument
$file = resolve-path($filePath)

if (!$file)
{
    Write-Host "Could not find the configuration file specified. Aborting." -ForegroundColor red       
    Break
}

write-host "Parsing file: " $file
$XmlDoc = [xml](Get-Content $file)

                #Preparing connection manager#

        $site = new-object Microsoft.SharePoint.SPSite($siteName);  
        $context = [Microsoft.SharePoint.SPServiceContext]::GetContext($site);  

        if (!$context)
        {
        write-host "context is empty, quitting!"
        break
        }

            #$context = new-object Microsoft.SharePoint.SPServiceContext.GetContext($site); 
            $UPAConfMgr = new-object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager($context)

        if (!$UPAConfMgr)
        {
        write-host "confmgr is empty, quitting!"
        break
        }

        $UPAConnMgr = $UPAConfMgr.ConnectionManager
                $userprofiletype = [Microsoft.Office.Server.UserProfiles.ProfileType]::User
                    $CurrentConnection = $UPAConnMgr | where {$_.AccountDomain -eq $ConnectionDomain}
                $PropertyMapping = $CurrentConnection.PropertyMapping

                                $userProfilePropertyManager = $UPAConfMgr.ProfilePropertyManager
                                $userProfileTypeProperties = $userProfilePropertyManager.GetProfileTypeProperties($userprofiletype)

                                #Creating core properties
                                $CoreProperties = $UPAConfMgr.ProfilePropertyManager.GetCoreProperties()                              

                    #####################
                    #Creating properties#
                    #####################

Write-Host "Creating user profile properties." -ForegroundColor green
                                $PropertyNodeList = $XmlDoc.Connections.Connection.PropertyCreations

                                #Checking if the servicecontext (the site specified in the  attribute
                                #in the parse file actually exist. If not, we cannot continue.
                                if (!$context) 
                                {
                                                Write-Host "There are entries in the  node in the parse file, but the  node contains a URL to a site that does not exist. Critical error, cannot continue." -ForegroundColor red
                                                Break
                                }
                                $userProfileSubTypeManager = [Microsoft.Office.Server.UserProfiles.ProfileSubtypeManager]::Get($context)
                                $userProfile = $userProfileSubTypeManager.GetProfileSubtype([Microsoft.Office.Server.UserProfiles.ProfileSubtypeManager]::GetDefaultProfileName($userprofiletype))
                                $userProfileProperties = $userProfile.Properties

        #$userProfileProperties.RemovePropertyByName("State");  
        #write-host -f red "deleted state"
        #break

                                foreach ($PropertyNode in $PropertyNodeList.ProfilePropertyCreation) 
                    {
            #write-host "Creating " $PropertyNode.InnerText
                                    if ($PropertyNode)
                                                {
               #$ProfilePropertyCreation.Privacy = "public"
                #$ProfilePropertyCreation.PrivacyPolicy = "option"

                                                                #Fetching information for the new property.   userOverridePrivacy="0" isReplicable="1"
                                                                $ProfilePropertyCreation = $PropertyNode#.SelectSingleNode("ProfilePropertyCreation")
                                                                $SharePointProp = $ProfilePropertyCreation.InnerText
                                                                $SharePointPropDisplayName = $ProfilePropertyCreation.DisplayName
                                                                $SharePointPropPrivacy = $ProfilePropertyCreation.Privacy.ToLower()
                                                                $SharePointPropPrivacyPolicy = $ProfilePropertyCreation.PrivacyPolicy.ToLower()
                                                                $SharePointPropType = $ProfilePropertyCreation.PropType.ToLower()
                                                                $SharePointPropLength = $ProfilePropertyCreation.PropLength
                                                                $SharePointPropIsVisibleOnEditor = $ProfilePropertyCreation.IsVisibleOnEditor
                                                                $SharePointPropIsVisibleOnViewer = $ProfilePropertyCreation.IsVisibleOnViewer
                                                                $SharePointPropDisplayOrder = $ProfilePropertyCreation.DisplayOrder
                                                                $SharePointPropIsEventLog = $ProfilePropertyCreation.IsEventLog
                                                                $SharePointPropIsUserEditable = $ProfilePropertyCreation.IsUserEditable
                                                                $SharePointUserOverrideprivacy = $ProfilePropertyCreation.UserOverridePrivacy  
                                                                $SharePointSectionName = $ProfilePropertyCreation.Section     

                                                                $SharePointPropDisplayOrder = [int]$SharePointPropDisplayOrder                                                                                                                         

                                                                #Basic syntax checking of $SharePointPropPrivacy attribute
                                                                $PrivacyMembers = "public", "contacts", "Organization", "Manager", "Private"
                                                                if (!($PrivacyMembers -contains $SharePointPropPrivacy))
                                                                {
                                                                                Write-Host "The new SharePoint property `"$SharePointProp`" contains an invalid privacy attribute ($SharePointPropPrivacy). The allowed entries are: public, contacts, Organization, Manager, Private. Skipping attribute." -ForegroundColor red
                                                                                Continue
                                                                }

                                                                #Basic syntax checking of $SharePointPropPrivacyPolicy attribute
                                                                $PrivacyPolicyMembers = "mandatory", "optin","optout", "disabled"
                                                                if (!($PrivacyPolicyMembers -contains $SharePointPropPrivacyPolicy))
                                                                {
                                                                                Write-Host "The new SharePoint property `"$SharePointProp`" contains an invalid privacy policy attribute ($SharePointPropPrivacyPolicy). The allowed entries are: mandatory, optin,optout, disabled. Skipping attribute $SharePointProp." -ForegroundColor red
                                                                                Continue
                                                                }

                                                                #Basic syntax checking of $SharePointPropType attribute
                                                                if ($SharePointPropType -ne "string")
                                                                {
                                                                                Write-Host "Currently the script only able to create `"String`" type of attributes. The attribute provided is: $SharePointPropType. Skipping attribute $SharePointProp." -ForegroundColor red
                                                                                Continue
                                                                }

                                                                #Basic syntax checking of $SharePointPropLength attribute
                                                                $loaderror = [Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
                                                                if ($loaderror -ne "Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
                                                                {
                                                                                $IsNumber = [Microsoft.VisualBasic.Information]::isnumeric($SharePointPropLength)

                                                                                if (!$IsNumber)
                                                                                {
                                                                                                Write-Host "The property length specified for this attribute is invalid. Skipping attribute $SharePointProp." -ForegroundColor red
                                                                                                Continue
                                                                                }
                                                                }

                                                                #Basic syntax checking of $SharePointPropLength attribute
                                                                $loaderror = [Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
                                                                if ($loaderror -ne "Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
                                                                {
                                                                                $IsNumber = [Microsoft.VisualBasic.Information]::isnumeric($SharePointPropDisplayOrder)

                                                                                if (!$IsNumber)
                                                                                {
                                                                                                Write-Host "The property length specified for this attribute is invalid. Skipping attribute $SharePointPropDisplayOrder." -ForegroundColor red
                                                                                                Continue
                                                                                }
                                                                }

                                                                if($SharePointPropIsVisibleOnEditor -eq "1")
                                                                {
                                                                    $SharePointPropIsVisibleOnEditor = $true
                                                                }
                                                                else
                                                                {
                                                                    $SharePointPropIsVisibleOnEditor = $false
                                                                }
                                                                if($SharePointPropIsVisibleOnViewer -eq "1")
                                                                {
                                                                    $SharePointPropIsVisibleOnViewer = $true
                                                                }
                                                                else
                                                                {
                                                                    $SharePointPropIsVisibleOnViewer = $false
                                                                }
                                                                if($SharePointPropIsEventLog -eq "1")
                                                                {
                                                                    $SharePointPropIsEventLog = $true
                                                                }
                                                                else
                                                                {
                                                                    $SharePointPropIsEventLog = $false
                                                                }
                                                                if($SharePointPropIsUserEditable -eq "1")
                                                                {
                                                                    $SharePointPropIsUserEditable = $true
                                                                }
                                                                else
                                                                {
                                                                    $SharePointPropIsUserEditable = $false
                                                                }
                                                                 if($SharePointUserOverrideprivacy -eq "1")
                                                                {
                                                                    $SharePointUserOverrideprivacy = $true
                                                                }
                                                                else
                                                                {
                                                                    $SharePointUserOverrideprivacy = $false
                                                                }                                                              

                                                                $sec = $userProfileProperties.GetSectionByName($SharePointSectionName);

                                                                $NewUPProperty = $userProfileProperties.GetPropertyByName($SharePointProp)   #sproperty

                                                                if($NewUPProperty -eq $null)
                                                                {
                               Write-Host "Creating " $sharepointpropdisplayname                                 

                                                                #Creating a NewProperty with basic attributes
                                                                $NewProperty = $CoreProperties.Create($false)
                                                                $Newproperty.Name = $SharePointProp
                                                                $NewProperty.DisplayName = $SharePointPropDisplayName
                                                                $NewProperty.Type = $SharePointPropType
                                                                $NewProperty.Length = $SharePointPropLength

                            #Write-Host $sharepointpropdisplayname 

                                                                #Adding the new property to the core properties list
                                                                $CoreProperties.Add($NewProperty)

                                                                #Reinitializing the newly created property to change secondary attributes.
                                                                $NewTypeProperty = $userProfileTypeProperties.Create($NewProperty)                                                                

                                                                #Display attributes
                                                                $NewTypeProperty.IsVisibleOnEditor = $SharePointPropIsVisibleOnEditor
                                                                $NewTypeProperty.IsVisibleOnViewer = $SharePointPropIsVisibleOnViewer 
                                                                $NewTypeProperty.IsEventLog = $SharePointPropIsEventLog

                                                                #Updating the new property's secondary attributes
                                                                $userProfileTypeProperties.Add($NewTypeProperty)

                                                                #Reinicializing the newly created property to privacy attributes.
                                                                $NewSubProperty = $userProfileProperties.Create($NewTypeProperty)
                                                                $NewSubProperty.DefaultPrivacy = [Microsoft.Office.Server.UserProfiles.Privacy]::$SharePointPropPrivacy
                                                                $NewSubProperty.PrivacyPolicy = [Microsoft.Office.Server.UserProfiles.PrivacyPolicy]::$SharePointPropPrivacyPolicy

                                                                $NewSubProperty.IsUserEditable = $SharePointPropIsUserEditable

                                                                $NewSubProperty.UserOverridePrivacy = $SharePointUserOverrideprivacy

                                                                #Finalizing the new property.
                                                                $userProfileProperties.Add($NewSubProperty)

                                                                }
                                                                else
                                                                {

                                                        Write-Host "Updating " $sharepointpropdisplayname     

                                                                $NewUPTypeProperty = $userProfileTypeProperties.GetPropertyByName($SharePointProp)

                                                                $NewUPTypeProperty.CoreProperty.DisplayName = $SharePointPropDisplayName    

                                                                $NewUPTypeProperty.IsVisibleOnViewer = $SharePointPropIsVisibleOnViewer 
                                                                $NewUPTypeProperty.IsVisibleOnEditor = $SharePointPropIsVisibleOnEditor
                                                                $NewUPTypeProperty.IsEventLog = $SharePointPropIsEventLog

                                                                $NewUPProperty.DefaultPrivacy = [Microsoft.Office.Server.UserProfiles.Privacy]::$SharePointPropPrivacy
                                                                $NewUPProperty.PrivacyPolicy = [Microsoft.Office.Server.UserProfiles.PrivacyPolicy]::$SharePointPropPrivacyPolicy

                                                                $NewUPProperty.IsUserEditable = $SharePointPropIsUserEditable                                                                
                                                                $NewUPProperty.UserOverridePrivacy = $SharePointUserOverrideprivacy

                                                                $NewUPTypeProperty.CoreProperty.Commit()
                                                                $NewUPProperty.Commit()
                                                                $NewUPTypeProperty.Commit()

                                                                }

                                                                $err = $userProfileProperties.GetEnumerator()

                                                                #Setting the display order
                                                                if($ProfilePropertyCreation.DisplayOrder -ne "0")
                                                                {
                                                                    $userProfileProperties.SetDisplayOrderByPropertyName($SharePointProp,$sec.DisplayOrder + $SharePointPropDisplayOrder)
																	Write-Host "    Set user profile property `"$SharePointProp`"." " with display order $SharePointPropDisplayOrder +" $sec.DisplayOrder                                                     
                                                                }

                                                                Write-Host "    User profile property `"$SharePointProp`"." " added or updated"
                                                }
                                                else
                                                {
                                                                Write-Host "There are no profiles to be created in the parse file."
                                                }
                                }

                                $userProfileProperties.CommitDisplayOrder()

The input file format looks like this -

<?xml version="1.0" encoding="utf-8"?>
<Connections>
  <Connection name="Test">
    <PropertyCreations>
      <ProfilePropertyCreation DisplayName="Education" Privacy="public" PrivacyPolicy="optin" UserOverridePrivacy="1" PropType="string" PropLength="25" IsUserEditable="1" IsVisibleOnEditor="1" IsVisibleOnViewer="1" IsEventLog="1" DisplayOrder="0" Section="SPS-Section-Details">SPS-School</ProfilePropertyCreation>
    </PropertyCreations>
  </Connection>
</Connections>

The attributes in the input file are pretty direct and have a direct correlation to the attributes found in central admin. The extra attributes to note here are “DisplayOrder” and “Section”. These are used for ordering the attribute. “Section” refers to the section name which will contain our user profile property and “Order” refers to the position of our attribute inside the specified section.

To re-order a section, use a script like this-

 $sec = $userProfileProperties.GetSectionByName("SPS-Section-ContactInfo");  
 Write-Host $sec.DisplayOrder;
 $userProfileProperties. SetDisplayOrderBySectionName("MySection",$sec.DisplayOrder+12)

This script fetches the order of the “Contact Info” section and adds a custom section named “MySection” (created earlier) after that.

Also, please note that the above script currently works only for string type properties but it can be very easily modified to accomodate all kinds of properties. Also, it doesnot map the properties to AD props.

Managed Navigation(or Term based navigation) in SharePoint 2013 – How manageable is it and how to configure global navigation across multiple site collections

Managed navigation is introduced in SharePoint 2013. It provides a great way to build and manage navigation of a site collection and completely decouples the navigation from the actual site structure. The following post explains nicely how to configure navigation -

Term based navigation in SharePoint 2013

Now, coming to the manageability part, you can manage navigation for a site collection very easily by simply managing its navigation termset.

Unfortunately, all these bells and whistles are only limited to a particular site collection. SharePoint 2013 allows a termset to be associated only to a single site collection for navigation. So, if you want to have a consistent/same navigation across multiple site collections, there is no direct way to implement and manage it. Let us analyse the indirect ways in detail :

1) Create a master navigation termset with all the required navigation terms in the proper order. Associate it to the site collection to provide the navigation structure. For any other site collection which needs the same navigation, create a new navigation termset (dont add any new terms) and reuse/pin all the terms from the master navigation termset. Follow the same process for all site collections that need the same navigation.

Note : Add the url to each term as “Simple Link or Header”, else in many scenarios, it will not appear for other site collections.

Let us discuss the pros and cons of this approach -

Pros

a) Any name/property changes (except some – mentioned in cons) to terms in master termset will be reflected across all other termsets with reused/pinned terms.
b) The term GUIDs in reused term sets are same as the master termset. This will be helpful to manage them via code/powershell.

Cons

a) Since, you need to create a separate termset for each site collection, the no of termsets may be huge.
b) The custom order of terms and child terms in master termset is not propagated to other termsets even though they reuse the same terms.
c) If a navigation url is changed for a term in master termset, it also doesnot get propagated to other termsets.

You can write a powershell to create terms, reuse terms in other termsets, set the term order and also for propagation of order to reused terms, association of termset to site collection etc. This will ease a lot of burden. I will share a script very soon.

2) Create a completely custom navigation provider which uses the termset as the source for links and builds the navigation by itself. I will share a sample soon.

3) Write a custom javascript to workaround these issues to a good extent. A nice sample is available in the following blog -

Building global navigation in SharePoint 2013

Narahari

Using Like and Rating functionality in SharePoint 2013 Pages (and SP2013 Custom like button)

Wow!!! SharePoint 2013 includes Like and Rating functionality out of the box. Just navigate to List/Library Settings -> Rating settings and set it up. It is that easy :-) .

Library Settings

However, you can only like/unlike or rate a item/page in the “All Items” view of the list/library. So, If you want to show this flashy “Like” functionality to your users on different publishing pages of your site, there is no out of the box way to do it. In this post, I will explain a simple way to add a custom like button to your publishing pages by using SharePoint’s built in Javascript methods. I will also give pointers on how to add a rating button to your page.

Like Button

(In the image above, I have changed the image for the Like Button to display a Thumbs up instead of a smiley.)

In a nutshell, the process goes like this. Create/modify the page layout/add a content editor used for the content pages of your site to add a little html. Then enable the liking settings on the library (mostly Pages Library) where the content/publishing pages are stored. Reference a small Javascript code in your masterpage/page layout and add some css to style your Like button. Finally, deploy the custom javascript file to SharePoint.

Now, let us understand the process in detail.

1. Create/modify the page layout or add :

Page Layout provides an excellent way to maintain a consistent and desirable look and feel for your content pages in the site. Most of the publishing sites use custom page layouts. If you do not use custom Page Layouts, don’t worry. You can still do this by adding a simple content editor webpart/script editor to your pages and adding the same code inside that. Add the following html code to your Page layout/content editor.

<div class="LikeSection"><span class="likecount"></span><a href="#" onclick="LikePage()" class="LikeButton"></a></div>

Explanation : In the above html code, the anchor tag will be our Like/Unlike button and the span will display the no of likes for the current page. I have added classes to all these elements and enclosed them in a div so that you can give your own look and feel to the like section :-) .

2. Enable liking settings on the library -

Navigate to library settings -> Rating Settings. Select the option “Yes” for “Allow items in this list to be rated” and select “Likes” for “Which voting/rating experience you would like to enable for this list”.

Explanation : Once you enable liking, SharePoint will add two columns to the list named “LikedBy” and “LikesCount”. As the names suggest, “LikedBy” will store the user identities who liked the item and “LikesCount” will store the no of likes respectively. This step builds the SP liking infrastructure for you.

3. Create the javascript file -

Create a javascript file named Like.js and paste the following code into it.

function LikePage() {
    var like = false;
    var likeButtonText = $("a.LikeButton").text();
    if (likeButtonText != "") {
        if (likeButtonText == "Like")
            like = true;

        var aContextObject = new SP.ClientContext();
        EnsureScriptFunc('reputation.js', 'Microsoft.Office.Server.ReputationModel.Reputation', function () {
            Microsoft.Office.Server.ReputationModel.
            Reputation.setLike(aContextObject,
                _spPageContextInfo.pageListId.substring(1, 37),
                _spPageContextInfo.pageItemId, like);

            aContextObject.executeQueryAsync(
                function () {
                    //alert(String(like));
                    GetLikeCount();
                }, function (sender, args) {
                    //alert('F0');
                });
        });
    }

}

function GetLikeCount() {

    var context = new SP.ClientContext(_spPageContextInfo.webServerRelativeUrl);
    var list = context.get_web().get_lists().getById(_spPageContextInfo.pageListId);
    var item = list.getItemById(_spPageContextInfo.pageItemId);

    context.load(item, "LikedBy", "ID", "LikesCount");
    context.executeQueryAsync(Function.createDelegate(this, function (success) {
        // Check if the user id of the current users is in the collection LikedBy. 
        var likeDisplay = true;
        var $v_0 = item.get_item('LikedBy');
        var itemc = item.get_item('LikesCount');
        if (!SP.ScriptHelpers.isNullOrUndefined($v_0)) {
            for (var $v_1 = 0, $v_2 = $v_0.length; $v_1 &lt; $v_2; $v_1++) {
                var $v_3 = $v_0[$v_1];
                if ($v_3.$1E_1 === _spPageContextInfo.userId) {
                    //cb(true, item.get_item('LikesCount'));
                    //alert("Liked by me");
                    likeDisplay = false;
                }
            }
        }
        ChangeLikeText(likeDisplay, itemc);

    }), Function.createDelegate(this, function (sender, args) {
        //alert('F1');
    }));

}

function ChangeLikeText(like, count) {
    if (like) {
        $("a.LikeButton").text('Like');
    }
    else {
        $("a.LikeButton").text('Unlike');
    }
    var htmlstring = "<img alt="" src="/_layouts/15/images/LikeFull.11x11x32.png" />" + " " + String(count);
    if (count &gt; 0)
        $(".likecount").html(htmlstring)
    else
        $(".likecount").html("");
}

$(document).ready(function () {
    GetLikeCount();
    $("a.LikeButton").click(function () {
        LikePage();
    });
});

Explanation : In our Like.js JS file, we have 4 methods -

LikePage() – This function calls the out of the box SharePoint method named “Microsoft.Office.Server.ReputationModel.Reputation.setLike” present in the “Reputation.js” javascript file (present inside Layouts folder). To see the function clearly, open the readable version of the file called “Reputation.debug.js”. This setLike function takes the parameters – context, listId, itemId and like(bool). We get the current context very easily using the SP.ClientContext(). Then we use the properties of the magical variable “_spPageContextInfo” to get the list ID and item ID respectively. Finally we pass the 4th parameter which is boolean to like or unlike a page.

GetLikeCount() – This function queries the list to get the “LikesCount” for the current list item (in our case, current page). It also checks the field “LikedBy” to see if the current user’s id is present in it to determine whether the current user has liked the page or not. Then it passes these values to the ChangeLikeText function.

ChangeLikeText() – This function displays the total likes for the current page and changes the text of the anchor tag to Like or Unlike based on whether the current user has liked the page or not.

Finally, in the document ready function, we display the like count and add the click handler to the like button.

4. Reference JS and css files -

If you have many content pages, just reference the SharePoint JS files in your masterpage as shown below. You can also reference them in your Page Layout if you wish to.

<SharePoint:ScriptLink ID="ScriptLink6" name="SP.js" runat="server" ondemand="false" localizable="false" loadafterui="true" />
<SharePoint:ScriptLink ID="ScriptLink8" name="SP.Core.js" runat="server" ondemand="false" localizable="false" loadafterui="true" />
<SharePoint:ScriptLink ID="ScriptLink9" name="Reputation.js" runat="server" ondemand="false" localizable="false" loadafterui="true" />
<script src="/_layouts/15/InSite/Scripts/Like.js" type="text/javascript"></script>

As you can see, the last one is a link to our like.js file which will do all the magic for us.

Add the following css to your global css file or inside PageLayouts

.likecount {
margin-right:5px;
}

.LikeSection {
margin-bottom:15px;
}

5. Deploy Like.js -

You can deploy this into any custom folder inside layouts folder or into a library. Accordingly, change the path to like.js file in our step 4.

Similarly, if you want to add rating control to your page, leverage the function “Microsoft.Office.Server.ReputationModel.Reputation.SetRating” instead of “SetLike” in out custom javascript file and change the logic slighly to display the rating stars instead of Like controls.