SharePoint: Making the User Profile Manager Property Mandatory


In this post we will be making the User Profile Manager property a mandatory element when users update their user profile.

Spoiler

This could quite possibly be the most pointless post ever, because the User Profile Manager property cannot be set to Required. The Manager property is a OOTB/system property and the policy setting controls in both the property editor and policy editor pages are disabled.

The vague reason for this is because the Manager property is somewhat special in that, a person having a Manager property with a value of NULL conveys a notion of leadership, and is used by SharePoint (amongst other things) to determine things like social distance and search relevance.

Spencer Harbar has a good post related to this subject, which elaborates on a facility to otherwise determine “Leadership” attributes of User Profiles.

If you’re interested in a facsimile solution then read on.

From Central Admin » User Profile Service Application, editing the Manager profile property or policy shows that the Policy setting control is disabled;

Policy Settings
Policy Settings
Property Settings
Property Settings

So, faced with a requirement from a client to make this property required, I came up with this solution.

Note

This solution assumes that the Manager profile property has been setup with an Export mapping in the user profile synchronisation connection – if the direction is Import (AD -> SharePoint) is makes no sense to make the Manager property editable anyway since it would get overwritten after a profile synch.

Requirements.

  • Clearly not everyone in an organisation can have a manager, you’d expect that at least one person being a big cheese wouldn’t have a manager, so the solution needs to have an exclusion list; i.e. people in a list who are not required to have a manager.
  • For users who are not in this exclusion list, we need to modify the user profile edit page to enforce that the Manager property (people picker control) has a valid value.

Deployment.

The Mysite host site collection hosts the view and edit pages for all users to view and edit their user profiles, and so we will deploy our assets here.

First up is the requirement for the exclusion list, this is a very simple list with a single Content Type which includes a Title column and a User column called “Organisation User”;

Exclusion List
Exclusion List

Here we can add users who are not required to have a Manager;

Hail Bob the Leader
Hail Bob the Leader

Again, this list is hosted on the rootweb of the Mysite host site collection.

So thats the exclusion list done, next we need to introduce code onto the user profile edit page, which does the following;

  • Determine if the current user is listed in the exclusion list, if they are then there is nothing to do since, as mentioned, the Manager property and control is optional anyway.
  • The user is required to have a Manager;
    • We need to update the display markup for the manager control to indicate its “required field” status
    • We need to wrap the OK button clicks (top and bottom buttons) to verify that a value for the Manager property is present
    • If the Manager control is empty or doesn’t contain a validated value, we need to show them some informational toast
    • If the Manager control contains a valid value, then we need to perform the default OK button action, which is to do the OK button postback

This part of the solution is a piece of javascript which uses the JSOM to query the exclusion list, and if required, to modify the user interface as discussed above. We will host this script in a user control and deploy it with an “AdditionalPageHead” delegate control.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
	<Control Id="AdditionalPageHead" 
				ControlSrc="~/_CONTROLTEMPLATES/pdogs.profilemanager/pdogs-mysite-requiremanager.ascx" 
				Sequence="50" />
</Elements>

Note

The user profile edit page (EditProfile.aspx) doesn’t have a convenient delegate control specific to the page which I could have used to deploy the user control, therefore the script is effectively present on every page of the Mysite host site collection.

The user control is a simple user control with no (server) code-behind and the user control markup simply holds the <script /> element.

The first part of the script determines if the user is on the user profile edit page, and if so, queries the exclusion list for a listitem with an “Organisation User” column equal to the current user.

var ctx = null;
var userId = null;
var collLeaderItems = null;

ExecuteOrDelayUntilScriptLoaded(initialisePage, "SP.js");

function initialisePage() {
	// if this isn't the edit profile page then bail
	if (location.href.indexOf('EditProfile.aspx') === -1) return;

	if (typeof(_spPageContextInfo) === 'undefined' || _spPageContextInfo === null) {
		alert("Error in initialisePage(): _spPageContextInfo is null or undefined!");
		return;
	}
	userId = _spPageContextInfo.userId;
	
	ctx = new SP.ClientContext.get_current();
	var list = ctx.get_web()
				.get_lists()
				.getByTitle('Organisation Leaders');
	
	var camlQuery = new SP.CamlQuery();
	camlQuery.set_viewXml("<View><Query><Where>"+
							"<Eq><FieldRef Name='pdogOrganisationUser' LookupId='TRUE' /><Value Type='Integer'>" 
								+ userId +
							"</Value></Eq></Where></Query></View>");
	collLeaderItems = list.getItems(camlQuery);
	
	ctx.load(collLeaderItems);
	ctx.executeQueryAsync(function () {
		onSuccessSetupUI();
	}, function (sender, args) {
		alert('Error in initialisePage():\n' 
				+ args.get_message() + '\n' 
				+ args.get_stackTrace());
	});
}

The next part modifies the user interface to add the “required field” markup to the manager control and sets up the wrapping of the OK buttons click handling;

function onSuccessSetupUI() {
	var count = collLeaderItems.get_count();
	if (count > 0) {
		// bail! the current user is not required to have a Manager
		return;
	}

	// add a click handler to save buttons top and bottom
	$(	"a[id$='ProfileSave_Top'],a[id$='ProfileSave_Top_i'],"+
		"a[id$='ProfileSave_Bottom'],a[id$='ProfileSave_Bottom_i']")
			.click(function(e) {
				 return pdWrappedPostBack(e,this);
			});

	// add a "required" field indicator to manager property editor
	$("td.ms-rightAlign > span")
		.filter(function () { return $(this).text() == "Manager:"; })
		.closest("td")
		.each(function() { $(this).append("<span class="ms-error"> *</span>"); });
}

And finally the wrapped OK buttons click handler;

function pdWrappedPostBack(e,a) {
	// check for resolved people entitites in Manager property editor
	var people = $("DIV[id$='EditManager_upLevelDiv']").find("SPAN.ms-entity-resolved");
	if (people.length != 1) {
		// show status bar
		$("#s4-statusbarcontainer")[0].scrollIntoView();
		var sid = SP.UI.Status.addStatus(
			"<img style="margin-right: 10px; vertical-align: middle;" alt="" src="/_layouts/images/warn16.gif" border="0" />"+
				"Profile Validation:",
			"You must enter a value for the Manager property.", true);
		SP.UI.Status.setStatusPriColor(sid, 'red');

		// setup status bar removal
		setTimeout(function () { SP.UI.Status.removeStatus(sid); }, 5000);
		return false;
	}

	// get/evaluate the postback reference
	var cmd = a.href.split("javascript:")[1];
	return eval(cmd);
}

If the manager control doesn’t have a resolved entity, we create a status notification after scrolling the status bar container DIV into view, which is useful because the edit profile page can be quite long.

If the manager control does have a resolved entity, then we simply evaluate the OK buttons original javascript code contained in the elements href attribute, which performs the postback.

The edit profile page when not required to have a manager;

Manager Not Required
Manager Not Required

The edit profile page when required to have a manager;

Manager Required
Manager Required

Attempting to save when there isn’t a valid manager property value;

Manager Not Entered
Manager Not Entered

Published by

Phil Harding

SharePoint Consultant, Developer, Father, Husband and Climber.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.