A way of accessing User Profile properties is trough UserProfileManager. If you are an administrator you can read/update/create properties. If you are not admin then you are in trouble. You cannot read or update properties even running with elevated privileges.
A solution is to give all authenticated users the right to edit their profiles:
Navigate to Central Admin Navigate to the Shared Service Provider Under User Profiles and My Sites navigate to Personalization services permissions . If the account doesn't already exist, add the account for which your sites App Domain is running under. Grant that user Manage user profiles permission Another way is to use web services as described below.
The idea is to use the UserProfileService.asmx. (http://localhost/_vti_bin/userprofileservice.asmx)
For this as a first step you must create a web reference to this service and give a name to this reference.
In my case the property is a string. First instantiate your object:
public static UPS.UserProfileService ups = new UPS.UserProfileService();
The code is simple. Please remember that the user under the application pool is running must have the “Manage user profiles” permission.
public static string GetTheCurrentUserPropertyFromWS()
{
String theproperty = String.Empty;
ups.Url = GetServiceUrl();
ups.Credentials = System.Net.CredentialCache.DefaultCredentials;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
try
{
string userName = System.Web.HttpContext.Current.User.Identity.Name;
UPS.PropertyData propertyData = GetPropertyFromUser(userName);
if (propertyData != null && propertyData.Values.Length != 0 && !string.IsNullOrEmpty(propertyData.Values[0].Value as string))
{
theproperty = (string)propertyData.Values[0].Value;
}
}
catch (Exception ex)
{
throw new NullReferenceException(string.Format("Error: {0} ; User profile for user {1} not found."
, ex.Message + ups.Url
, System.Web.HttpContext.Current.User.Identity.Name));
}
});
return theproperty;
}
private static bool SetPropertyForCurrentUserFromWS(string propertyAsString)
{
bool allOK = true;
ups.Url = GetServiceUrl();
ups.Credentials = System.Net.CredentialCache.DefaultCredentials;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
try
{
string userName = System.Web.HttpContext.Current.User.Identity.Name;
UPS.PropertyData propertyData = GetPropertyFromUser(userName);
if (propertyData != null)
{
UpdatePropertyToUser(userName, propertyAsString);
}
}
catch (Exception ex)
{
allOK = false;
throw new NullReferenceException(string.Format("User profile for user {0} not found."
, System.Web.HttpContext.Current.User.Identity.Name + ups.Url));
}
});
return allOK;
}
private static UPS.PropertyData GetPropertyFromUser(string userName)
{
UPS.PropertyData returnpropertyData = null;
UPS.PropertyData[] userpropertydata = ups.GetUserProfileByName(userName);
foreach (UPS.PropertyData pd in userpropertydata)
{
if (pd.Name == "MyPropertyName")
{
returnpropertyData = (UPS.PropertyData)pd;
break;
}
}
return returnpropertyData;
}
private static void UpdatePropertyToUser(string userName, string result)
{
// the property already exist - must only update
UPS.PropertyData[] newdata = new UPS.PropertyData[1];
newdata[0] = new UPS.PropertyData();
newdata[0].Name = "MyPropertyName";
newdata[0].Values = new UPS.ValueData[1];
newdata[0].Values[0] = new UPS.ValueData();
newdata[0].Values[0].Value = result;
newdata[0].IsValueChanged = true;
ups.ModifyUserPropertyByAccountName(userName, newdata);
}
private static string GetServiceUrl()
{
StringBuilder sb = new StringBuilder();
string suffixUrl = "_vti_bin/userprofileservice.asmx";
Uri theUri = new Uri(SPContext.Current.Site.Url);
string prefixUrl = theUri.AbsoluteUri;
if (theUri.AbsolutePath != @"/")
{
prefixUrl = prefixUrl.Replace(theUri.AbsolutePath, "");
sb.Append(prefixUrl).Append(@"/").Append(suffixUrl);
}
else
{
sb.Append(prefixUrl).Append(suffixUrl);
}
return sb.ToString();
}
Now you can get or set values for user properties. Remember that the property must be already created. You cannot create one using a web service.