16 June 2007

Updating and Enumerating User Profiles in MOSS

Recently, we came across a situation in our environment in which we needed to enumerate all profiles in MOSS 2007 and add a few new profile properties. One of the properties that needed to be updated is the picture url. All of our employees pictures are located in a separate database and an image handler has already been created to serve out the images. So, we wanted to leverage this to place user pictures into the directory (and turn off the user's ability to modify them).

This project is a service that will run on my MOSS server a pre-determined intervals. I will eventually add it to SharePoint as a timer job to be done just after the user profile import has completed.

So, here's the code that made it work:

Imports Microsoft.SharePoint Imports Microsoft.Office.Server.UserProfiles Imports Microsoft.Office.Server
Module UserProfileUpdaterService
Sub Main()
Dim currentSite As New SPSite("http://mymossserver/") Dim context As ServerContext = ServerContext.GetContext(currentSite) Dim profileManager As New UserProfileManager(context)
For Each profile As UserProfile In profileManager
' Get profile properties Dim FirstNameProp As UserProfileValueCollection = profile.Item("FirstName") Dim LastNameProp As UserProfileValueCollection = profile.Item("LastName") Dim ImageProp As UserProfileValueCollection = profile.Item("PictureURL")
' Get string values from the properties Dim FirstName As String = FirstNameProp.Item(0) Dim LastName As String = LastNameProp.Item(0) Dim PictureURL As String = ImageProp.Item(0)
' Set a new picture URL PictureURL = String.Format("http://imageserver/GetEmployeeImage.ashx?" & _ "e={0}",GetEmployeeID(FirstName,LastName))
' Set the image property and commit the changes ImageProp.Item(0) = PictureURL profile.Commit()
Next
End Sub
End Module

First, we need to get a SPSite. This is done by creating a new instance of SPSite passing the site URL to the constructor. Next, we have to pass the site context to the user profile manager's constructor. Then we can iterate through all profiles and retrieve properties of the profile. Each property is returned as a UserProfilePropertyValueCollection. You can get an individual property by calling Prop.Item("PropertyName"). This will return an array of objects. Since most of the properties I'm working with are strings, there's not much of a need to cast them to other object types. Finally, I query the database with the method GetEmployeeID(FirstName,LastName) (which I have not detailed here) and write the values back into the image property using ImageProp.Item(0)=PictureURL. To write the changes to the profile, I finally call profile.Commit.

Hope this simple example can help some of you make necessary changes to your user profile stores in MOSS 2007.

06 June 2007

10 Things I Despise about SharePoint Workflows

Okay, I'm fed up with the lack of documentation and examples for sharepoint workflows. Here are the top ten things that are bugging me about this: 1) Incomplete documentation 2) Sparse or overly complex examples 3) Few experts and community support 4) Weakly integrated tools (both SharePoint designer and VS 2005) 5) Disconnected assumptions about workflow forms (association, initialization and modification) 6) Extremely poorly documented examples of state machine workflows 7) Poor information on creating deployment solutions 8) Continually recursive looping of some workflows with no blocking mechanizm 9) Single instance workflows removing previous historical information 10) Examples are primarily in C# and are difficult to translate to my VB programmers. There... I've said it. I'm ready to learn more and begin building solutions, but until these top ten items are resolved, it will be difficult treading. The problem -- I have 3 weeks to complete a complex workflow problem! Grr...