I recently ran into a nasty situation where I needed a reliable way to get a list of user Full Names (or Display Names) from a list of usernames in a SharePoint process.
The short answer was easy… The code runs server side so…
SPUser theUser = web.EnsureUser(username);
string DisplayName = theUser.Name;
//Right?
Well, under normal circumstances, sure.
In this circumstance, I was checking a list of lists of user names, a condition where I might need to check hundreds of items, each of which could have a list of users to check.
No biggie, just add a lookup table and cache the results over multiple calls so that I only ever have to look a user up once in my process.
Now here’s the real kicker. In my target environment, EnsureUser comes back instantly if the username is a valid, active user in Active Directory. If the user is not a valid user? The command takes over 40 seconds per call to fail!
My solution was two-fold.
1) use the aforementioned cache strategy, which I have in my sample code below as _nameMap.
2) Use a simple worker thread. Give it two seconds to succeed. Kill the thread if it takes longer than that for any reason.
I initially made the mistake of using SPContext.Current.Web in the thread, but that can *sometimes* produce a threading violation. The code below creates a whole new instance of SPSite/SPWeb on every pass, but that’s a lot safer and better performing than a lot of alternatives.
private Dictionary _nameMap = new Dictionary();
private string GetUsersWithTempCacheAndTimeoutEnforcement(string rawUsers)
{
string result = string.Empty;
SPContext.Current.Web.AllowUnsafeUpdates = true;
foreach (string aUser in rawUsers.Split(';'))
{
try
{
string addUser = string.Empty;
string checkUser = aUser.Split('#')[1];
if (checkUser.Contains("\\"))
{
lock (_nameMap)
{
if (_nameMap.ContainsKey(checkUser))
{
addUser = _nameMap[checkUser] + "; ";
}
else
{
SPUser userResult = null;
SPContext context = SPContext.Current;
string webUrl = context.Web.Url;
System.Threading.ThreadStart st = new System.Threading.ThreadStart(
() =>
{
try
{
using (SPSite site = new SPSite(webUrl))
{
using (SPWeb web = site.OpenWeb())
{
userResult = web.EnsureUser(checkUser);
}
}
}
catch (Exception)
{ }
});
System.Threading.Thread workThread = new System.Threading.Thread(st);
workThread.Start();
workThread.Join(2000);
if (workThread.IsAlive)
{
workThread.Abort();
}
if (userResult == null)
{
_nameMap[checkUser] = checkUser;
addUser = checkUser + "; ";
}
else
{
_nameMap[checkUser] = userResult.Name;
addUser = userResult.Name + "; ";
}
}
}
}
result += addUser;
}
catch (IndexOutOfRangeException)
{
}
catch (Exception ex)
{
}
}
return result;
}