UserProfileManager oManager = GetUserProfileManager();
UserProfile oProfile = oManager.GetUserProfile(sUsername);
oProfile["SomePropertyName"].Value = "This is a nice value to set";
If you try this then, happily, it will probably work. That is unless you have a multi-value property. Well - it will work if you have a multi-value property, as long as you are only setting a single value.
Let me explain.... it looks at first glance as if the property is just an object with a 'Value' property accessed via the indexer, it's a little more than that. The property is, in fact, a UserProfileValueCollection object. Indeed, apparently it's a UserProfileValueCollection object even if it's not a multi-value field - it just has a default indexer to the first object in the collection so that you'd never realise it was a collection. This is why the syntax I showed above for a single value worked OK.
So when will it not work? Well, try and do this with a multi-value property when you have a constrained choice list (comma-separated in this case):
oProfile["SomePropertyName"].Value = "Multivalue 1, Multivalue 2, Multivalue 3";
It will throw an exception along the lines of 'thats not a valid option'. This is because it is trying to find an option in the choice list that matches the whole string. It is not 'intelligent' enough to try and break down the string into separate values.
(side note - the 'Separator' property of the Property object, which is of type MultiValueSeparator enum, appears to be only related to how the UI itself captures or presents the data. Behind the scenes, the data is stored in a collection and the Separator property is pretty much redundant. In fact, you could build your own UI elements to manipulate the value collection and you can totally ignore that Separator property, if you wished.)
So, how to fix it? Well, luckily its actually very simple. In the above example, you'd just do this:
((UserProfileValueCollection)oProfile["SomePropertyName"]).Add("Multivalue1");
((UserProfileValueCollection)oProfile["SomePropertyName"]).Add("Multivalue2");
((UserProfileValueCollection)oProfile["SomePropertyName"]).Add("Multivalue3");
If you wanted to be very clean about it, or it was an automated process which didn't know what type the property was, then you could use the following technique to check for a multi-value (assuming oManager and oProfile are initialised as per the top of this blog post):
if(oManager.Properties.GetPropertyByName["SomePropertyName"].IsMultiValued)
{
// do the multi-value stuff
}
else
{
// treat as a single value
}
I hope this helps someone out because the Microsoft documentation, at the moment, is a little sparse.