I had a requirement from our client that we need to update some of the user AD properties with the SharePoint user profile properties regularly.
So, for that i have build a console application to update the properties and i have scheduled it as a Windows scheduler.
I have kept all the settings (LDAP connection string, AD admin username, password etc.. ) in the app.config file so that i don't have to specify them in the code.
Below is the App.Config file code.
<appSettings>
<add key="tenantAdministrationUrl" value=""/>
<add key="tenantAdminLoginName" value=""/>
<add key="tenantAdminPassword" value=""/>
<add key="UserProfileProperties" value="WorkPhone|CellPhone"/>
<add key="UserProfilePrimeProperty" value="WorkEmail"/>
<add key="LDAP" value="LDAP://OU="/>
<add key="ADAdminUserName" value="" />
<add key="ADAdminPassword" value="" />
<add key="Properties" value="telephoneNumber|mobile"/>
<add key="PrimeProperty" value="mail"/>
</appSettings>
Below is the code to retrieve the settings from the app.config file.
So, for that i have build a console application to update the properties and i have scheduled it as a Windows scheduler.
I have kept all the settings (LDAP connection string, AD admin username, password etc.. ) in the app.config file so that i don't have to specify them in the code.
Below is the App.Config file code.
<appSettings>
<add key="tenantAdministrationUrl" value=""/>
<add key="tenantAdminLoginName" value=""/>
<add key="tenantAdminPassword" value=""/>
<add key="UserProfileProperties" value="WorkPhone|CellPhone"/>
<add key="UserProfilePrimeProperty" value="WorkEmail"/>
<add key="LDAP" value="LDAP://OU="/>
<add key="ADAdminUserName" value="" />
<add key="ADAdminPassword" value="" />
<add key="Properties" value="telephoneNumber|mobile"/>
<add key="PrimeProperty" value="mail"/>
</appSettings>
Below is the code to retrieve the settings from the app.config file.
Consts._UserProfilePrimeProperty = ConfigurationManager.AppSettings["UserProfilePrimeProperty"];
Consts.ADAdminUserName = ConfigurationManager.AppSettings["ADAdminUserName"];
Consts.ADAdminPassWord = ConfigurationManager.AppSettings["ADAdminPassWord"];
Consts._ProfileProperties = ConfigurationManager.AppSettings["Properties"];
Consts._PrimeProperty = ConfigurationManager.AppSettings["PrimeProperty"];
Consts._tenantAdministrationUrl = ConfigurationManager.AppSettings["tenantAdministrationUrl"];
Consts._tenantAdminLoginName = ConfigurationManager.AppSettings["tenantAdminLoginName"];
Consts._tenantAdminPassword = ConfigurationManager.AppSettings["tenantAdminPassword"];
Consts._UserProfileProfileProperties = ConfigurationManager.AppSettings["UserProfileProperties"];
Below method will retrieve the AD information.
Below is the method which will import AD data to user profile.
public static void ImportDatatoCloud(TextWriter writer)
{
List<Dictionary<string, ExpandoObject>> dataCollection = Consts.UserProdDataCol;
int count = 1;
int totalUsers = dataCollection.Count;
foreach (var dataCol in dataCollection)
{
Generic.LogMessage(string.Format("processing user '{0}' of {1}...", count, totalUsers), Consts.LogLevel.Information);
var userName = dataCol.Keys.FirstOrDefault();
dynamic propertySet = dataCol.Values.FirstOrDefault();
string UserAccountName = Consts._sPOProfilePrefix + userName;
try
{
using (ClientContext clientContext = new ClientContext(Consts._tenantAdministrationUrl))
{
SecureString passWord = new SecureString();
foreach (char c in Consts._tenantAdminPassword.ToCharArray()) passWord.AppendChar(c);
clientContext.Credentials = new SharePointOnlineCredentials(Consts._tenantAdminLoginName, passWord);
// Get the people manager instance for tenant context
PeopleManager peopleManager = new PeopleManager(clientContext);
foreach (var property in propertySet)
{
string propName = property.Key;
string propVal = property.Value;
Console.WriteLine(userName + " - " + propName + "->" + propVal);
if (propVal.Contains('|'))
{
// List Multiple values
List<string> propValues = propVal.Split('|').ToList<string>();
// Update the SPS-Skills property for the user using account name from profile.
peopleManager.SetMultiValuedProfileProperty(UserAccountName, propName, propValues);
}
else
{
// Update the AboutMe property for the user using account name.
peopleManager.SetSingleValueProfileProperty(UserAccountName, propName, propVal);
}
}
clientContext.ExecuteQueryRetry();
}
}
catch (Exception ex)
{
Console.WriteLine("Issue in updating the profile properties for :" + UserAccountName);
writer.WriteLine("Issue in updating the profile properties for :" + UserAccountName);
writer.WriteLine(ex.ToString());
}
count++;
}
Generic.LogMessage("Processing finished for " + totalUsers + " user profiles. Import Complete!", Consts.LogLevel.Warning);
}
Points to remember:
Remember to add the sharepoint online client dll's - Microsoft.SharePoint.Client.dll, Microsoft.SharePoint.Client.Runtime.dll, Microsoft.SharePoint.Client.UserProfiles.dll
Hope this code helps you.
Happy Coding :)
Consts.ADAdminUserName = ConfigurationManager.AppSettings["ADAdminUserName"];
Consts.ADAdminPassWord = ConfigurationManager.AppSettings["ADAdminPassWord"];
Consts._ProfileProperties = ConfigurationManager.AppSettings["Properties"];
Consts._PrimeProperty = ConfigurationManager.AppSettings["PrimeProperty"];
Consts._tenantAdministrationUrl = ConfigurationManager.AppSettings["tenantAdministrationUrl"];
Consts._tenantAdminLoginName = ConfigurationManager.AppSettings["tenantAdminLoginName"];
Consts._tenantAdminPassword = ConfigurationManager.AppSettings["tenantAdminPassword"];
Consts._UserProfileProfileProperties = ConfigurationManager.AppSettings["UserProfileProperties"];
Below method will retrieve the AD information.
public static void getADInformation()
{
string ldap = ConfigurationManager.AppSettings["LDAP"];
Console.WriteLine(ldap);
if (!string.IsNullOrEmpty(ldap))
{
try
{
using (DirectoryEntry ou = new DirectoryEntry(ldap))
{
DirectorySearcher searcher = new DirectorySearcher(ou);
searcher.Filter = "(&(objectClass=user)(objectCategory=person))";
searcher.SearchScope = SearchScope.Subtree;
searcher.PageSize = 1000;//This has to be set to return all the results from AD, if not set then it will limit the results to 1000 only
string[] tempProp = Consts._ProfileProperties.Split('|');
string[] properties = new string[tempProp.Count() + 1];
properties[0] = Consts._PrimeProperty;
for (int i = 1; i <= tempProp.Count(); i++)
{
properties[i] = tempProp[i - 1];
}
foreach (var property in properties)
{
searcher.PropertiesToLoad.Add(property);
}
SearchResult result;
List<string[]> columnValues = new List<string[]>();
searcher.PropertiesToLoad.Add("userPrincipalName");
searcher.PropertiesToLoad.Add("samAccountName");
SearchResultCollection resultCol = searcher.FindAll();
Console.WriteLine("Find all");
if (resultCol != null)
{
Console.WriteLine(resultCol.Count + " Results found in AD");
for (int i = 0; i < resultCol.Count; i++)
{
result = resultCol[i];
Console.WriteLine(result.Properties["samAccountName"][0] + "-" + result.Properties["userPrincipalName"][0]);
string[] tempPropVal = new string[properties.Count()];
int propCnt = 0;
//get each property value to array
foreach (var property in properties)
{
if (result.Properties.Contains(property))
{
tempPropVal[propCnt] = Convert.ToString(result.Properties[property][0]);
}
else
{
tempPropVal[propCnt] = "";
}
propCnt++;
}
columnValues.Add(tempPropVal);
}
}
string[] tempUserProfileProp = Consts._UserProfileProfileProperties.Split('|');
string[] userProfileProperties = new string[tempUserProfileProp.Count() + 1];
userProfileProperties[0] = Consts._UserProfilePrimeProperty;
for (int i = 1; i <= tempUserProfileProp.Count(); i++)
{
userProfileProperties[i] = tempUserProfileProp[i - 1];
}
Consts.UserProdDataCol = new List<Dictionary<string, ExpandoObject>>();
foreach (string[] columnValue in columnValues)
{
dynamic data = new ExpandoObject();
//get the first object which is the account
string account = columnValue[0];
Dictionary<string, ExpandoObject> userProfData = new Dictionary<string, ExpandoObject>();
if (!string.IsNullOrEmpty(account))
{
for (int j = 1; j < userProfileProperties.Count(); j++)
{
((IDictionary<String, Object>)data).Add(userProfileProperties[j], columnValue[j]);
}
userProfData.Add(account, data);
Consts.UserProdDataCol.Add(userProfData);
}
else
{
Console.WriteLine(account + " is empty");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
}
Below is the method which will import AD data to user profile.
public static void ImportDatatoCloud(TextWriter writer)
{
List<Dictionary<string, ExpandoObject>> dataCollection = Consts.UserProdDataCol;
int count = 1;
int totalUsers = dataCollection.Count;
foreach (var dataCol in dataCollection)
{
Generic.LogMessage(string.Format("processing user '{0}' of {1}...", count, totalUsers), Consts.LogLevel.Information);
var userName = dataCol.Keys.FirstOrDefault();
dynamic propertySet = dataCol.Values.FirstOrDefault();
string UserAccountName = Consts._sPOProfilePrefix + userName;
try
{
using (ClientContext clientContext = new ClientContext(Consts._tenantAdministrationUrl))
{
SecureString passWord = new SecureString();
foreach (char c in Consts._tenantAdminPassword.ToCharArray()) passWord.AppendChar(c);
clientContext.Credentials = new SharePointOnlineCredentials(Consts._tenantAdminLoginName, passWord);
// Get the people manager instance for tenant context
PeopleManager peopleManager = new PeopleManager(clientContext);
foreach (var property in propertySet)
{
string propName = property.Key;
string propVal = property.Value;
Console.WriteLine(userName + " - " + propName + "->" + propVal);
if (propVal.Contains('|'))
{
// List Multiple values
List<string> propValues = propVal.Split('|').ToList<string>();
// Update the SPS-Skills property for the user using account name from profile.
peopleManager.SetMultiValuedProfileProperty(UserAccountName, propName, propValues);
}
else
{
// Update the AboutMe property for the user using account name.
peopleManager.SetSingleValueProfileProperty(UserAccountName, propName, propVal);
}
}
clientContext.ExecuteQueryRetry();
}
}
catch (Exception ex)
{
Console.WriteLine("Issue in updating the profile properties for :" + UserAccountName);
writer.WriteLine("Issue in updating the profile properties for :" + UserAccountName);
writer.WriteLine(ex.ToString());
}
count++;
}
Generic.LogMessage("Processing finished for " + totalUsers + " user profiles. Import Complete!", Consts.LogLevel.Warning);
}
Points to remember:
Remember to add the sharepoint online client dll's - Microsoft.SharePoint.Client.dll, Microsoft.SharePoint.Client.Runtime.dll, Microsoft.SharePoint.Client.UserProfiles.dll
Hope this code helps you.
Happy Coding :)
No comments:
Post a Comment