Tag Archive: PeopleEditor


This post is an update to a previous post I had written on validating the PeopleEditor control on post back. In that particular post, I described the challenges of getting a PeopleEditor control, within a custom application page, to validate correctly as a required field on the client side (I had server side validation already in place and working correctly).

For the most part, the solution I outlined worked well, except for some situations where other controls on the page were performing their own post back (for example, a data grid in edit mode). I found that on submit of the entire form, the ASP.NET required field validator for the PeopleEditor control would kick in informing me that the field was required. However, there was a valid entry in the control so I could only conclude that the post back by some other control on the page was mucking up the view state for the PeopleEditor control and on submit the form was no longer aware that this field did in fact have a value in it.

The MSDN article found here outlines my problem exactly with the eventual solution further down in the thread. I just wanted to highlight it here because it was exactly what I needed to resolve my issue. Thank you to Jan Lange for posting his solution!

1
2
3
4
5
6
7
8
<script language="javascript">  
    function CheckProjectManager(source, arguments) {  
        if (aspnetForm.ctl00_PlaceHolderMain_ProjectManager_downlevelTextBox.value == "")  
            arguments.IsValid = false;  
        else  
            arguments.IsValid = true;  
    }  
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<SharePoint:PeopleEditor   
                ID="ProjectManager"   
                AllowEmpty="false"   
                ValidatorEnabled="true"   
                MultiSelect="false" 
                runat="server"   
                SelectionSet="User" 
                Width="200px"   
                TabIndex="2" />
 
<asp:CustomValidator  
                ID="rfvProjectManager" 
                runat="server" 
                ControlToValidate="" 
                ErrorMessage="Required" 
                Enabled="true"   
                ClientValidationFunction="CheckProjectManager">  
                </asp:CustomValidator>

Just to outline, what Jan eventually did was create a custom validator that called a javascript function to validate the control. Within that function he checks to see if the control is empty and stores the results of the validation in the IsValid property of the ServerValidateEventArgs object. Notice that he also sets the ControlToValidate property to “”.

Hope this helps!

I was recently working on a Black Ninja Software project for a client of ours where performance became an issues for one of the custom application pages we had developed. I plan to write up a more detailed report on how I managed to cut the load times of this particular page in half using the ANTS Profiler, but for now I wanted to highlight a piece of the puzzle that I discovered today.

I won’t cover how to load values into a PeopleEditor control from within a SharePoint list, you can view that in more detail here.

Take a look at the example below:

1
2
3
SPFieldUserValue user = new SPFieldUserValue(web, Convert.ToString(listItem["Employee]));
 
peEmployee.CommaSeparatedAccounts = user.LookupValue;

If we have an SPFieldUserValue object, calling upon the LookupValue property will return the Name of that user. This is not to be confused with the LoginName property. Assigning that to the CommaSeparatedAccounts property may do the trick and will load that user account into the control but not without a performance hit.

A better approach would be:

1
2
3
SPFieldUserValue user = new SPFieldUserValue(web, Convert.ToString(listItem["Employee"]));
 
peEmployee.CommaSeparatedAccounts = user.User.LoginName;

The difference is minor. Instead of using the LookupValue property, we leverage the SPUser object and call upon the LoginName property. In all of my testing, I noticed an improvement in speed when using the LoginName property.

Depending on your environment, the output from either of those properties will differ and that’s the heart of the performance issues. In my environment, LoginName and Name outputted the following:

Name – “Joe User”
LoginName – “domain\juser”

Having the domain specified seems to speed this whole process up. I would be interested to hear from anyone else who’s encountered anything similar.

Validating a PeopleEditor Control on PostBack

Let’s talk about validation and the PeopleEditor control. There doesn’t seem to be a consensus on how this is supposed to be done so I’ll outline my findings and what eventually worked for me.

I’ll start by explaining what I was attempting to do. I have a PeopleEditor control on a custom application page. My custom application page is located in the _layouts directory. On this page, I also have a submit button that saves my data to a SharePoint list upon submit.

Now, I need to ensure before submit, that the PeopleEditor control contains a valid entry. Blank and invalid values are not permitted.

I first attempted to set the AlllowEmpty property to false. However, that didn’t seem to help. If I clicked submit, the page would post back and then the control would display an error once the page reloaded. At this point, it was too late to be informing the user that there was a problem with their entry, the page had already posted back, so this was not useful.

I also tried setting the ValidationEnabled property to true. That didn’t seem to make any difference either. I am confused as to how these two properties are supposed to work.

My next attempt was to add an ASP.NET required field validator to the page as follows:

1
2
3
<wssawc:PeopleEditor AllowEmpty="false" ValidatorEnabled="true" Width="250px" ID="pePR" runat="server" SelectionSet="User" MultiSelect="false" />
 
<asp:RequiredFieldValidator ID="rfvPR" ControlToValidate="pePR" runat="server" ErrorMessage="Project Requestor (Cannot be blank)" Text="Cannot be blank." ValidationGroup="SubmitForm" Display="Dynamic"></asp:RequiredFieldValidator>

This took care of the client side validation that prevented the user from clicking submit without first entering a value into the control.

However, this did not handle the scenario when a user entered an invalid value in the control and hit submit. In this case, the form will attempt to submit and create the item, but will fail to save the value to the list item field because the value was invalid. An example of an invalid value would be bad data in that field.

To fix this, in my submit method, I added an IF statement to check how many resolved entities there were.

1
2
3
4
5
6
if (pePR.ResolvedEntities.Count > 0) {
    // continue with the submit
}
else {
    // output an error that the user did not enter a valid user
}

If anyone has any feedback, or has had success using the AllowEmpty property, please comment on this post or drop me a note. I’m interested in hearing how others were able to get around this issue.

The PeopleEditor control is a common control that you’ll find implemented throughout SharePoint. If you’re building any custom web parts or application pages, you may want users to enter people specific information. The PeopleEditor is a good choice, however, there isn’t much out there in terms of documenting it’s use. Hopefully the information below will help get you started. If you are having issues, or if there is something I’ve missed in my post, please feel free to leave me a comment.

NOTE: One thing I found was that in order for this control to successfully save a user, that user has to exist within the site collection. If they don’t exist, the web.SiteUsers call will fail with an exception ‘user cannot be found’.

UPDATE: You can use the EnsureUser method to verify that the specified user exists and is a valid user of the web site. The neat thing about this method is that it will add the user to the site if they do not already exist, thus making the SiteUsers call unnecessary. Keep in mind that if you do use this method, you may need to elevate permissions to make that call, as not all users have access to add other users to your site collection.

To get started, create a new Custom List named Demo. Within List Settings, create a column of type Person or Group named Managers.

In this particular example, I’ll be building a custom application page with a single PeopleEditor control and a submit button. Create a new page (or download the files I’ve prepared for this article here), called Demo.aspx and store it in the _layouts directory.

Since the people editor control is located within the Microsoft.SharePoint.WebControls namespace, you’ll have to register the tag prefix at the top of your page:

1
<%@ Register TagPrefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Insert the control on the page. If you look at my Demo.aspx page, I’ve put my control within a table tag, but you can format this however you’d like:

1
<wssawc:PeopleEditor AllowEmpty="false" Width="300px" id="peManagers" runat="server" SelectionSet="User" />

AllowEmtpy – let’s you specify if blank values are permitted for this control
SelectionSet – can be User or SecGroup or SPGroup or all three: User, SecGroup, SPGroup
MultiSelect – set to true or false, false if you don’t want the user to be able to select more than one

Insert an asp:Button control onto the page; we’ll use this to submit the people data to the list.

1
<asp:Button ID="btnSubmit" runat="server" OnClick="btnSubmit_Click" ValidationGroup="Main" Text="OK" CssClass="ms-ButtonHeightWidth" />

In order to save values from the control to the column we created, you’ll need the following code in the button submit event:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
protected void btnSubmit_Click(object sender, EventArgs e)
{
    // create a web object with context for the current site
 
    SPWeb web = SPContext.Current.Web;
 
    // get the entries that were entered into the people editor and store them in a string
 
    string managers = peManagers.CommaSeparatedAccounts;
 
    // commaseparatedaccounts returns entries that are comma separated. we want to split those up
 
    char[] splitter = { ',' };
 
    string[] splitPPData = managers.Split(splitter);
 
    // this collection will store the user values from the people editor which we'll eventually use
    // to populate the field in the list
 
    SPFieldUserValueCollection values = new SPFieldUserValueCollection();
 
    // for each item in our array, create a new sp user object given the loginname and add to our collection
 
    for (int i = 0; i < splitPPData.Length; i++)
    {
        string loginName = splitPPData[i];
 
        if (!string.IsNullOrEmpty(loginName))
        {
            SPUser user = web.SiteUsers[loginName];
 
            // you could also use SPUser user = web.EnsureUser(loginName);
 
            SPFieldUserValue fuv = new SPFieldUserValue(web, user.ID, user.LoginName);
 
            values.Add(fuv);
        }
 
    }
 
    // set the Person or Group column
 
    SPListItemCollection listItems = web.Lists["Demo"].Items;
 
    SPListItem manager = listItems.Add();
 
    manager["Managers"] = values;
 
    manager.Update();
}

That should do it. You should be able to save the entries to the list. If you’d like to learn how to read values from a list column into a PeopleEditor control, you can read that post here. Any feedback?

This post was really planned as a Part 2 to the first post I made about saving data from the PeopleEditor control. My aim for this entry is to tackle the reverse scenario: reading data from a field of type Person or Group and loading it into a PeopleEditor control. If you have any troubles with Part 1 or Part 2 of this series or if there’s something I’ve missed, I would love to hear about it. Leave a comment or drop me an email. Thanks!

If you’ve followed Part 1 of this series, you should already have a list named Demo created with a column of type Person or Group named Managers. If not, begin by creating a new Custom List named Demo. Within List Settings, create a column of type Person or Group and name it Managers. Set the Allow multiple selections checkbox to Yes.

Once you’ve created the list and the column, add a few new entries so we have some data to load.

Now let’s create a custom application page with a single PeopleEditor control on it. Create a new page (or download it here) called Load.aspx and store it in the layouts directory.

Since the people editor control is located within the Microsoft.SharePoint.WebControls namespace, you’ll have to register the tag prefix at the top of your page:

1
<%@ Register TagPrefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Insert the control on the page. This is the control we’ll be loading the data into:

1
<wssawc:PeopleEditor AllowEmpty="false" Width="300px" id="Managers" runat="server" SelectionSet="User" />

The next step will require that we wire up our Page_Load event to load the necessary data from the list to the control.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
protected void Page_Load(object sender, EventArgs e)
{
 
    try
    {
 
        SPWeb web = SPContext.Current.Web;
 
        // get a handle to the list we’ll be pulling values from
        SPList list = web.Lists["Demo"];
 
        // using the querystring parameter containing the id, get the list item we’ll be dealing with
        SPListItem listItem = list.GetItemById(Convert.ToInt32(Request["id"]));
 
        // the managers column is of type Person or Group, so we can use a spfielduservaluecollection to     store the values from it
        SPFieldUserValueCollection users = (SPFieldUserValueCollection)listItem["Managers"];
 
        // our array will hold the entities we’ll use to eventually assign to the people editor control
        ArrayList entityArrayList = new ArrayList();
 
        // loop through each use in the collection, set the key, add to the array
        for (int i = 0; i < users.Count; i++)
        {
 
            PickerEntity entity = new PickerEntity();
            entity.Key = users[i].User.LoginName;
            entityArrayList.Add(entity);
 
        }
 
        Managers.UpdateEntities(entityArrayList);
 
    }
 
    catch (Exception ex)
    {
 
        Response.Write(ex.ToString());
 
    }
 
}

Now when you navigate to your page, pass the id of a valid item in the list, and the entries in the manager column should load: http://servername/_layouts/Load.aspx?id=1 (replace servername with the name of your MOSS install)

Powered by WordPress | Theme: Motion by 85ideas.