This blog post is a contribution from Mustaq Patel, an engineer with the SharePoint Developer Support team.
The end goal is to populate User Profile Property values from an external database. From SharePoint 2010 UI, this requires the following three steps:
1. Create BCS Model. Have Finder and SpecificFinder methods defined in it. Make sure the mode has unique identifier, which should match with the user profile property (for e.g., AccountName). A model created using SPD should work as well.
2. Create User Profile Synchronization Connection (Manage User Profile Service Application > Configure Synchronization Connections).
3. Associate out of the box user profile property (or custom property) to the BCS field (Manage User Profile Service Application > Manage User Properties > Edit Existing property or create a new custom property).
The code sample shown below achieves the points 2 & 3 specified above. It assumes that the BCS model is published and fetches data successfully (test by having an external list).
My external database has fields AAccountName (which is a primary key and will act as association to AccountName in user profile property) and AOffice (which I would like to map to a custom User Profile Property called MyOffice).
I also had to add a Filter which is associated to the AAccountName field. Here’s the screenshot of my external list.
After the code (shown below) executes, it creates User Profile Synchronization Connection in BCS (check CreateProfileConnectionMy() in the sample code).
This code sets association to the filter in BCS to Accountname user profile property (check CreateProfileConnectionMy and SetDSMLAttribute() method in the sample code).
User Profile Property mapping is done in method SetPropertyMapping. Now, you should see BCS fields available to associate with User Profile Property. I associated MyOffice to BCS field AOffice (check SetPropertyMapping() method in the sample code).
After running user profile synchronization, the end result should be to have values populated in MyOffice user profile property.
Few notes on the code:
- Setting List<DSMLAttribute> dsmlAttributesList and passing it to userProfileConfigManager.ConnectionManager.AddBusinessDataCatalogConnection is important and will populate BCS fields in User Profile properties. If you pass in empty DSMLAttribute list, the connection will be created but you will not see BCS fields in the drop-down when you go in to the user profile properties of a user profile and edit a particular property. Further, it seems that you also need the code in the method SetDSMLAttribute(). If that’s not present, the AddBusinessDataCatalogConnection gives an exception (FIM put error exception). The connection will get created, but if you do user profile sync (full or incremental), you will see that the property value is not getting populated from external database. This is what the problem I had a chance to work on was about.
- SetPropertyMapping() method, sets property mapping with BCS fields and will need to be called after the connection is created (after AddBusinessDataCatalogConnection). It also shows how to connect to BCS Service, get specific method and iterate through the TypeDescriptor and fields.
Here’s the entire code. It’s implemented as a farm level feature event receiver (OnFeatureActivated) code.
Hope this post was helpful!