Quantcast
Channel: Second Life of a Hungarian SharePoint Geek
Viewing all articles
Browse latest Browse all 206

Importing SharePoint user profile properties using BCS .NET Connectivity Assembly

$
0
0

Recently I received a question, how we could alter the pattern of the user display names in SharePoint, for example, use FirstName LastName instead of LastName, FirstName. A few weeks ago I read a similar discussion somewhere on the web, where the participants had very strange proposals for the problem, ranging from event receivers on the SharePoint user information list to SQL triggers (!) on the SharePoint content database tables.

My first idea was to alter the user profile import process to get the display name dynamically through a BCS .NET connectivity assembly based of values stored in Active Directory. Unfortunately, all of the user profile synchronization samples I found that involve BCS connections (like this or this) illustrate only static values based on SQL databases, but no .NET connectivity assembly.

I’ve started Visual Studio 2010 with a new Empty SharePoint Project, and added a new Business Data Connectivity Model item.

I’ve altered the .bdcm file as illustrated by the XML below.

Note: Most articles mention that one should implement a SpecificFinder method as well as a Finder method in the BCS model, however based on my experiments it is enough to implement only the SpecificFinder method.

  1. <?xml version="1.0" encoding="utf-8" standalone="yes"?>
  2. <Model    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.         xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  4.         xmlns="http://schemas.microsoft.com/windows/2007/BusinessDataCatalog"
  5.         Name="ADDispNameModel">
  6.   <LobSystems>
  7.     <LobSystem Name="ADDispNameModel" Type="DotNetAssembly">
  8.       <LobSystemInstances>
  9.         <LobSystemInstance Name="ADDispNameModel"/>
  10.       </LobSystemInstances>
  11.       <Entities>
  12.         <Entity Name="ADEntity" Namespace="ADDispName.ADDispNameModel" EstimatedInstanceCount="1000" Version="1.0.0.0">
  13.           <Properties>
  14.             <Property Name="Class" Type="System.String">ADDispName.ADDispNameModel.ADEntityService, ADDispNameModel</Property>
  15.           </Properties>
  16.           <Identifiers>
  17.             <Identifier Name="AccountName" TypeName="System.String" />
  18.           </Identifiers>
  19.           <Methods>
  20.             <Method Name="ReadItem">
  21.               <Parameters>
  22.                 <Parameter Direction="In" Name="id">
  23.                   <TypeDescriptor TypeName="System.String" IdentifierName="AccountName" Name="AccountName" />
  24.                 </Parameter>
  25.                 <Parameter Direction="Return" Name="returnParameter">
  26.                   <TypeDescriptor TypeName="ADDispName.ADDispNameModel.ADEntity, ADDispNameModel" Name="ADEntity">
  27.                     <TypeDescriptors>
  28.                       <TypeDescriptor TypeName="System.String" IdentifierName="AccountName" Name="AccountName" />
  29.                       <TypeDescriptor TypeName="System.String" Name="DisplayName" />
  30.                     </TypeDescriptors>
  31.                   </TypeDescriptor>
  32.                 </Parameter>
  33.               </Parameters>
  34.               <MethodInstances>
  35.                 <MethodInstance Type="SpecificFinder" ReturnParameterName="returnParameter" Default="true" Name="ReadItem" DefaultDisplayName="Read ADEntity"/>
  36.               </MethodInstances>
  37.             </Method>
  38.           </Methods>
  39.         </Entity>
  40.       </Entities>
  41.     </LobSystem>
  42.   </LobSystems>
  43. </Model>

The ADEntity class holds the information on the AccountNameDisplayName values.

  1. namespace ADDispName.ADDispNameModel
  2. {
  3.     public partial class ADEntity
  4.     {
  5.         public string AccountName { get; set; }
  6.         public string DisplayName { get; set; }
  7.     }
  8. }

The ReadItem method of the ADEntityService class receives the account name as parameter, and gets the corresponding display name from the Active Directory using the custom pattern.

Note, that since the original format of the display name was already FirstName LastName in my case, I chose the FirstName LastName (Department) pattern as my custom display name format.

For the AD connection I used my custom ADUtils class.

  1. namespace ADDispName.ADDispNameModel
  2. {
  3.     public class ADEntityService
  4.     {
  5.         public static ADEntity ReadItem(string accountName)
  6.         {
  7.             ADUtils au = new ADUtils(accountName);
  8.  
  9.             ADEntity adEntity = new ADEntity();
  10.             adEntity.AccountName = accountName;
  11.             adEntity.DisplayName = string.Format("{0} {1} ({2})", au.FirstName, au.LastName, au.Department);
  12.             return adEntity;
  13.         }
  14.     }
  15. }

Having my BCS model deployed, I’ve created a new user profile synchronization connection as illustrated below:

image

Next, I’ve removed the default property mapping of the Name user profile property…

image

… and created a new import mapping from our BCS connection:

image

Finally, I’ve started a full user profile synchronization. After a while (near to the end of the process) the synchronization process accessed our custom connection:

image

Debugging the import process

If you try to debug the synchronization process, you find, that attaching the debugger to the SharePoint Timer Service (owstimer.exe) or to the SharePoint web application processes does not help.

So which process is responsible for calling our custom assembly? To answer the question, I used the trace messages from my ADUtils class, and the DebugView application.

image

From the trace it is clear, that the process is the miiserver.exe (process ID 3740 in my case). In Task Manager this process is identified as Forefront Identity Manager Synchronization Service.

image

Attaching our debugger (for example, Visual Studio) to this process, we can debug our custom BCS connectivity assembly.

image

Results of the synchronization

After the synchronization process finished, the changes are immediately visible in the user profiles:

 image

As a next step, we should propagate the changes from the user profile to the SharePoint sites. To achieve that, I’ve started the User Profile Service Application – User Profile to SharePoint Full Synchronization job:

image

After the job is executed, the new display name format should be visible in the SharePoint user information list:

image

in SharePoint items:

image

as well as in the People Picker:

image

You can download the sample project for this post from here.



Viewing all articles
Browse latest Browse all 206

Trending Articles