(a.k.a: why is this people picker breaking my form when I do more than one postback?!)
By: Philip Stathis
The People Picker is a great tool to present and validate data from SharePoint users and, indirectly, the Active Directory and is a valuable asset to any custom ASPX page.
The problem is, in all of its implementations across default SharePoint pages, the forms being used only appear on load and then get submitted. This process does only one post back. If you create a form with multiple people pickers like this one:

The user needs to be able to navigate this form while having set all these values in the people pickers and the viewstate would ordinarily be enough to handle that.
This is not the case.
NOTE: this was part of the August 2011 CU for SharePoint 2010 as can be seen here.
So if installing this CU is not an option, or this technique is applicable to you, here’s my work round:
Add this variable to your aspx page:
private static Hashtable userKeys = new Hashtable();
Next hit your Page_load logic:
protected void Page_Load(object sender, EventArgs e)
{
userKeys.Clear();
Session.Clear();
FormLogic.RetainPeopleEditors(Page.Controls, Session.SessionID, userKeys, out userKeys);
}
The method being used, along with dependant code snippets can be presented below
internal static void RetainPeopleEditors(ControlCollection controls, string sessionID, Hashtable userKeys, out Hashtable output)
{
ArrayList controlList = new ArrayList();
AddControls(controls, controlList);
foreach (PeopleEditor editor in controlList)
{
string key = editor.ID + sessionID;
if (userKeys.ContainsKey(key))
userKeys[key] = RetainPeople(editor, (ArrayList)userKeys[key]);
else
userKeys.Add(editor.ID + sessionID, RetainPeople(editor, (ArrayList)userKeys[editor.ID + sessionID]));
}
output = userKeys;
}
private static void AddControls(ControlCollection controlCollection, ArrayList controlList)
{
foreach (Control c in controlCollection)
{
if (c.ID != null)
{
if (c is PeopleEditor)
controlList.Add(c);
}
if (c.HasControls())
{
AddControls(c.Controls, controlList);
}
}
}
private static ArrayList RetainPeople(PeopleEditor pe, ArrayList userKey)
{
ArrayList peEntities = pe.ResolvedEntities;
if (peEntities.Count > 0)
{
ArrayList entities = peEntities;
return entities;
}
else if (userKey != null)
{
pe.UpdateEntities(userKey);
pe.Validate();
return userKey;
}
return null;
}
To provide an explanation of the method, you essentially create a HashTable that remains in the memory of the page, and append the keys with a session ID to ensure uniqueness when other people access your form.
As you may have noticed, the Picker Entity element cannot be stored in session since the class is not serializable.
This workaround will essentially stop the People Editor from having to grab values from the viewstate of the page. So this method is an assisted view state for people pickers.
Enjoy!
By: Philip Stathis