Saturday, August 22, 2009

Get SPUsers From SharePoint PeoplePicker Control

Code below shows how to retrieve SPUsers from the SharePoint PeoplePicker control when PeoplePicker control is set to only allow users (SelectionSet="User"):
<SharePoint:PeopleEditor id="peoplePicker" runat="server" AllowEmpty="true" ValidatorEnabled="true" MultiSelect="true" SelectionSet="Group"/>
public static List<SPUser> GetPeopleEditorUsers(PeopleEditor picker)
{
List<SPUser> users = new List<SPUser>();
try
{
foreach (PickerEntity entity in picker.ResolvedEntities)
{
if ((string)entity.EntityData["PrincipalType"] == "User")
{
int userID = Int32.Parse(entity.EntityData["SPUserID"].ToString());
SPUser user = SPContext.Current.Web.SiteUsers.GetByID(userID);
if (user != null)
{
users.Add(user);
}
}
}
}
catch (Exception ex)
{
//Log error
}
return users;
}
The code needs to be revised a bit when groups are included in the PeoplePicker (SelectionSet="SPGroup,DL,SecGroup"):
public static List<SPUser> GetPeopleEditorGroupUsers(PeopleEditor picker)
{
List<SPUser> users = new List<SPUser>();
try
{
foreach (PickerEntity entity in picker.ResolvedEntities)
{
if ((string)entity.EntityData["PrincipalType"] == "SharePointGroup")
{
int groupID = int.Parse((string)entity.EntityData["SPGroupID"]);
SPGroup group = SPContext.Current.Web.SiteGroups.GetByID(groupID);
foreach (SPUser user in group.Users)
{
users.Add(user);
}
}
}
}
catch (Exception ex)
{
//Log error
}
return users;
}
The difference between SPWeb.Groups and SPWeb.SiteGroups:
  • SPWeb.Groups: Groups explicitly assigned persmissions in a site collection.
  • SPWeb.SiteGroups: All valid groups available in the site collection (superset of SPWeb.Groups). You can add a new group to SPWeb.SiteGroups, but not the SPWeb.Groups.

The difference between SPWeb.AllUsers, SPWeb.SiteUsers and SPWeb.Users:
  • SPWeb.Users: Users explicitly assigned permissions in a site collection.
  • SPWeb.SiteUsers: All valid users available in a site collection (superset of SPWeb.Users).
  • SPWeb.AllUsers: All users who are either members of the site or who have browsed to the site as authenticated members of a domain group in the site (superset of SPWeb.SiteUsers).

Monday, August 10, 2009

32 Character Limit Of SharePoint List's Internal Field Name

I came cross a weird problem and found this issue. A DateTime field with name of "KSNF WebPart Update Time" is used in a custom Feature, and I can get or set its value without any problem using SharePoint API:
DateTime updatetime = Convert.ToDateTime(item["KSNF WebPart Update Time"]);
But I got nothing when using CAML query. Yes, I use interal name of "KSNF_x0020_WebPart_x0020_Update_x0020_Time" in my CAML query, and it returns empty. I use SharePoint Manager to check this field and see that its internal static name is "KSNF_x0020_WebPart_x0020_Update_". It's trimmed to 32-character!

So SharePoint only allows 32-character in field's internal (static) name? I created a simply console application to test that:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

public partial class Program
{
static void Main(string[] args)
{
string siteName = "http://localhost";
string listName = "Shared Documents";
string fieldName = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012345";

Console.WriteLine("Adding SPField to a SharePoint Document Library and a List with name of '{0}'", fieldName);
Console.WriteLine();
Console.WriteLine("Get SPField info from updated SharePoint Document Library:");
TestFieldName(siteName, listName, fieldName);
Console.WriteLine();

listName = "Announcements";
Console.WriteLine("Get SPField info from updated SharePoint List:");
TestFieldName(siteName, listName, fieldName);

Console.Read();
}

private static void TestFieldName(string siteName, string listName, string fieldName)
{
using (SPSite site = new SPSite(siteName))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[listName];
if (!list.Fields.ContainsField(fieldName))
{
list.Fields.Add(fieldName, SPFieldType.Text, false);
list.Update();
}
if (list.Fields.ContainsField(fieldName))
{
SPField field = list.Fields[fieldName];
Console.WriteLine("Display name:\t'{0}' {1}Static name:\t'{2}'",
field.Title, System.Environment.NewLine, field.StaticName);

list.Fields.Delete(fieldName);
list.Update();
}
}
}
}
}
The result is:
Adding SPField to a SharePoint Document Library and a List with name of
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012345'


Get SPField info from updated SharePoint Document Library:
Display name: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012345'
Static name: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012345'


Get SPField info from updated SharePoint List:
Display name: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012345'
Static name: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef'
Apparently the 32-character limit for internal field name only applies to SharePoint lists. There's no such limit for SharePoint document libraries.