Skip to content

Consolidating SharePoint User Profile Properties in InfoPath

January 7, 2011

The problem

We have multiple SharePoint farms and are replicating user profile information among the farms.

We need a consolidated view that includes User’s profile information in a specific farm, the information in each farm may or may not be correctly reflected in other farms.  This need is administrative in nature, but may have other uses.

In our environment we also use the columns of the Shared Document library in each MySite to store a replica of the User’s profile information (long story…)  So, we want to add to our consolidated view the values stored in the Shared Document library for that specific user

The Challenge

There are multiple challenges that we deal with in this solution.   We could write a web part and deploy it on the farm, but we wanted something quick and flexible (i.e. a solution that can easily be put in any farm).

Also, the Shared Documents library does not have a view!  So, we need to call a method that access the items of the library without a use of a view.

The Solution

OK.  not THE solution, just a solution.  InfoPath to the rescue!

InfoPath comes with ability to connect to external sources via web services, XML, or directly connected to a SharePoint list.  The latter method connects to a single list, and we are not going to use it.

In this solution we will do the following:

  1. Show all public user profile properties for any user, and show a single property
  2. Query the Shared Document list on the user’s MySite
  3. Show the user’s picture as bitmap

Creating the Data Connection

To get profile properties, we create a new data connection (Tools | Data Connections | Add).  Select “Create a new connection to:”  and “Receive data”.

Choose “Web service” for the source and enter the location as http://%5Bportal%5D/_vti_bin/userprofileservice.asmx.  In the next screen select GetUserProfileByName operation.  Clear the “Automatically..” checkbox on the last screen and click finish.

Presenting the Properties

Insert a text box and a button to your form.  The text box is used to input the account name that we want to search.

Click View | Design Tasks to reveal the Design Tasks pane and change to view “Data Source”.  change the data source to GetUserByProfileName, and drag the PropertyData into your document.   You can present it as repeating table or as repeating section with controls.  I choose Repeating table and delete all columns except name and values.  I change the text boxes to Expression boxes, which will show the entire value.  After some cleanup it looks like this:

image

To get the properties we add a “rule” to the search button.

As the first action we choose: “Set a field’s value”. Then open the “Select a Field or Group”image icon and change the data source to GetUserProfileByName open the query fields and choose “Account Name”.

For the value click on “Insert Formula” icon, “Insert a Field or Group” and select the LookupAccountName field (if you did not rename it, it is still called Field1.)

Next we add action and this time select “Query using a data connection” and choose the GetUserProfileByName data connection.

You can now Preview the form and enter a user account to get all their properties.  To select the current user properties, you can use the built-in function username().  You can also place that code in the “Open” event rules (Tools | Options | Open and save) with the built in user to show the current user by default.

Displaying Specific Properties

cycling and showing all properties can be a little too much.  What if we need more control over how to show individual properties? here is a quick way to pick one property from the list.  In this example we will use WorkPhone, which is a built-in SharePoint property.

We start by creating a field to hold the property.  add a text box to the form and name it WorkPhone.  You can set it to read-only or convert it to Expression Box later.  Then add an action to the rule you created in the previous step after the last action.

  1. select “Set a field’s value” for the action
  2. click on the “select a field or Group” icon and select the WorkPhone field that you just created
  3. click on the “Insert Formula” icon and then open “select a Field or Group”.  Change the data source to GetUserProfileByName.  Open dataFields and drill down to “value”.  With the dialog box still open, click on the “Filter Data” button, and add a filter such that Name = “WorkPhone”.  The results xpath looks like that:

 Value[Name = “WorkPhone”]

Query MySite Document Library

In this section we connect to the MySite library for each user.  We will need to use some code to dynamically connect InfoPath to a different sites and libraries.  The steps are outlined below:

  1. Create a data connection to read the values in a library for a specific user
  2. find out the URL of the user’s MySite
  3. find the GUID of Shared Documents library in that site
  4. Redirect the data connection to the library and read the data

We are going to use XML data from owssvr.dll to get list items.  create a new data source to “Receive Data” from “XML File.”  For file location enter: http://%5Bportal%5D/personal/%5Busername%5D/_vti_bin/owssvr.dll?Cmd=Display&List=%5Bguid%5D&Query=*&XMLDATA=TRUE

It’s a mouthful, but this initial location is just a placeholder to get all the fields.  You can find the GUID of the list in a number of ways.  I always have SharePoint Manager (http://spm.codeplex.com/), which makes makes tasks like these trivial.  SPM has to be installed on the server.

To find the GUID of the list programmatically from within InfoPath we create another Web Service data source.  This data source connects to http://%5Bportal%5D/_vti_bin/lists.asmx and attaches to the GetList operation.

Once the data source is connected, you can use it to add the fields to the form and make any modifications to their presentation.

Next, open the code editor (Tools | Programming) and type some support functions.

The first functions is the equivalent of the single property xpath mechanism above.  Given a property name it returns the value of the property.

private string GetProperty(string property)
{
    XPathNavigator nav = this.DataSources["GetUserProfileByName"].CreateNavigator();
    XPathNavigator prop = nav.SelectSingleNode(
        string.Format("/dfs:myFields/dfs:dataFields/s0:GetUserProfileByNameResponse/s0:GetUserProfileByNameResult/s0:PropertyData[s0:Name='{0}']/s0:Values/s0:ValueData/s0:Value", property), NamespaceManager);
    if (prop != null)
        return prop.Value;
    else return null;
}

another helper function dynamically changes the data connection to pic a new list

private static string RedirectLibrary(string listGuid, Uri current)
{
    UriBuilder builder = new UriBuilder(current);
    builder.Path += "_vti_bin/owssvr.dll";
    builder.Query = string.Format("Cmd=Display&List={0}&Query=*&XMLDATA=TRUE", HttpUtility.UrlEncode(listGuid) );
    return builder.Uri.AbsoluteUri;
}

We get the list GUID by executing and then accessing the GetList data connection with the following functions:

private void RedirectMySite(Uri url)
{
   WebServiceConnection wsConn = this.DataConnections["GetList"] as WebServiceConnection;
   wsConn.ServiceUrl = new Uri(string.Format("{0}_vti_bin/lists.asmx", url.ToString()));
   wsConn.Execute();
}

private string

GetSharedLibraryGuid() {
    XPathNavigator listNav = this.DataSources["GetList"].CreateNavigator();
    XPathNavigator listData = listNav.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetListResponse/tns:GetListResult/tns:List", NamespaceManager);
    return listData.GetAttribute("ID", "");
}

In your rules, you can set the ListName field of the query parameters for the GetList data connection to the name of the list (Shared Documents).  You can also add a line to the code to do the same.

Finally, the control main template function builds the URL to the user’s MySite with the help of PersonalSpace property in the user’s profile.  It calls the helper functions to redirect data sources to the new MySite and then executes the underlying connections.  The data on the form will change to reflect the new connections after you call “Execute()”.

private void ShowMySite()
{
    FileQueryConnection fConnection = this.DataConnections["ListAsXmlFile"] as FileQueryConnection;
    Uri fileLocation = new Uri(fConnection.FileLocation);
    Uri current = new UriBuilder(fileLocation.Scheme, fileLocation.Host, fileLocation.Port).Uri;
    ShowPicture(current);
    string mysiteUrl = GetProperty("PersonalSpace"); //fConnection.FileLocation if (!string.IsNullOrEmpty(mysiteUrl) && mysiteUrl.Contains("/"))
    {
        current = new Uri(current.AbsoluteUri + mysiteUrl);
        RedirectMySite(current);
Technorati Tags: ,
        // find the guid of the shared document list string listGuid = GetSharedLibraryGuid();

        // inject into mysite url fConnection.FileLocation = RedirectLibrary(listGuid, current);
        fConnection.Execute();
    }
}

Show Picture

One last touch is to show the picture of the image.  We add an empty Rich Text Box, named mypicture.

public void ShowPicture(Uri serverUrl)
{
    // load the picture XPathNavigator main = MainDataSource.CreateNavigator();
    XPathNavigator pictureField = main.SelectSingleNode("//my:mypicture", NamespaceManager);

    pictureField.InnerXml = string.Format("<img xmlns=\"http://www.w3.org/1999/xhtml\" src=\"{0}\"/>",
        GetProperty("PictureURL") ?? new Uri(serverUrl, "_layouts/images/no_pic.gif").ToString());
}

Conclusion

This code works for SharePoint 2007 and 2010 and with InfoPath 2007 and 2010.  The attached code references specific SharePoint sites and columns.  You will have to modify it with the techniques mentioned in this article to make it work for your site.

Load the code here Code for Show User Details.

Technorati Tags: ,
Advertisements

From → InfoPath, SharePoint

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: