Thursday, May 31, 2012

Configuring the User Profile Service in SharePoint 2010 {P3}
[working with user profile service Code level [vs 20101] - (how to get user detail , user properties and how to search users using user profile service)] 


With my previous posts [ P1 , P2 ] I have explained how to configure and Sync SharePoint User profile service with Active Directory and How to Map additional or Required field in UPS with AD attributes.


In this post I'm gonna explain and show how to work with our User profile service and do basic function in a programmatic way (Code Level). I'm gonna introduce there seperate function which help you to understand the way we need to deal with User Profile Service and the best practices specially when you deal with searching users.


Function No 1 : How to Search One User [most effective way]



Code:
using MicrosoftUserProfiles = Microsoft.Office.Server.UserProfiles;

        
        /// <summary>
        /// this will show one user detail
        /// </summary>
        /// <param name="site"></param>
        /// <param name="userId"></param>
        protected void showOneUser(SPSite site, string userId)
        {
            using (site)
            {
                LiteralControl lt = new LiteralControl();
                SPServiceContext context = SPServiceContext.GetContext(site);
                MicrosoftUserProfiles.UserProfileManager upm = new MicrosoftUserProfiles.UserProfileManager(context);
                //search one singel user using his accountname
                MicrosoftUserProfiles.UserProfile profile = upm.GetUserProfile(userId);
                String WorkEmail = profile[MicrosoftUserProfiles.PropertyConstants.WorkEmail].Value.ToString();
                String FirstName = profile[MicrosoftUserProfiles.PropertyConstants.FirstName].Value.ToString();
                String LastName = profile[MicrosoftUserProfiles.PropertyConstants.LastName].Value.ToString();

                lt.Text = "<br/><br/><b>WorkEmail :" + WorkEmail + "</b><br/><br/>";
                lt.Text += "<b>FirstName" + FirstName + "</b><br/>";
                lt.Text += "<b>LastName :" + LastName + "</b><br/>";
                lt.Text += "<b>ID :" + profile.ID + "</b><br/>";

                base.Controls.Add(lt);
            }
        }



Line by Line :


  1. using MicrosoftUserProfiles = Microsoft.Office.Server.UserProfiles;first you need to add Microsoft.Office.Server.UserProfiles.dll into reference. you can find it in following location "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.Office.Server.UserProfiles.dll" then import it. 
  2. Create user profile service instance which, help to get user details. MicrosoftUserProfiles.UserProfileManager upm = new MicrosoftUserProfiles.UserProfileManager(context);
  3. Get user detail using GetUserProfile() method, it returns UserProfile object which hold all the properties which extract from UserProfile service.               MicrosoftUserProfiles.UserProfile profile = upm.GetUserProfile(userId);
  4. Best practice is not to user string hard coded property names to get user details, instead of that you can use   PropertyConstants for that as   MicrosoftUserProfiles.PropertyConstants .WorkEmail Likewise 



Function No 2 : Show all the existing properties and data for one user [you can see Error if that property has not been configured well. ]



Code:
        /// <summary>
        /// this is show propety collection and fill data against to that
        /// </summary>
        /// <param name="site"></param>
        /// <param name="userId"></param>
        protected void showPropertyCollection(SPSite site, string userId)
        {
            using (site)
            {
                LiteralControl lt = new LiteralControl();
                SPServiceContext context = SPServiceContext.GetContext(site);
                MicrosoftUserProfiles.UserProfileManager upm = new MicrosoftUserProfiles.UserProfileManager(context);
                MicrosoftUserProfiles.UserProfile profile = upm.GetUserProfile(userId);
                // get all properties (Name and Display name only for testing purpose)
                Microsoft.Office.Server.UserProfiles.PropertyCollection propColl = profile.ProfileManager.PropertiesWithSection;
                if (profile != null && propColl != null)
                {
                    foreach (MicrosoftUserProfiles.Property prop in propColl)
                    {
                        try
                        {
                            lt.Text += "<br/><br/><b>property Name : " + prop.Name + "</b><br/>";
                            lt.Text += "<br/><b>property DisplayName : " + prop.DisplayName + "</b><br/>";
                            lt.Text += "<b>proerpty Value : " + profile[prop.Name] != null ? profile[prop.Name].Value : "empty" + "</b><br/>";
                        }
                        catch (Exception)
                        {
                            lt.Text += "<b>Error : </b><br/>";
                        }
                    }
                }

                base.Controls.Add(lt);
            }

        }




Line by Line :


  1. Microsoft.Office.Server.UserProfiles.PropertyCollection propColl = profile.ProfileManager.PropertiesWithSection; Use to get all the User Profile service properties and assign them in to property collection object.





Function No 3 : Search Data through user profile service and Bind the results into a Grid with paging.



Code:
        /// <summary>
        /// will search through user profil and bind result into the grid
        /// </summary>
        /// <param name="site"></param>
        /// <param name="searchPattern"></param>
        protected void searchThroughGrid(SPSite site, string searchPattern)
        {
            using (site)
            {
                SPServiceContext context = SPServiceContext.GetContext(site);
                // get all user profiles into User Profile Manage Object
                MicrosoftUserProfiles.UserProfileManager upm = new MicrosoftUserProfiles.UserProfileManager(context);
                //Search through that with given key word using profile base this is vary cost effective and performance wise perfect
                MicrosoftUserProfiles.ProfileBase[] searchResults = upm.Search(searchPattern);

                //create SP Grid view object and fill required propeties
                profileGrid = new SPGridView();
                profileGrid.AutoGenerateColumns = false;
                profileGrid.EnableViewState = true;
                profileGrid.AllowPaging = true;
                // Propety collection Binder class is holding all the required propeties and
                //functions which we can user to bind the data into the grid
                pcb = new PropertyCollectionBinder();
                foreach (MicrosoftUserProfiles.ProfileBase profileTemp in searchResults)
                {
                    // this loop will execute only for result not for it will not itrate through all User
                    //Profile data set which taken by User Profile Manager
                    MicrosoftUserProfiles.UserProfile up = upm.GetUserProfile(profileTemp.ID);
                    // here I only user few propeties we can configure them with our requirements
                    pcb.AddProperty(up[MicrosoftUserProfiles.PropertyConstants.AccountName].Value as string, up[MicrosoftUserProfiles.PropertyConstants.FirstName].Value as                     string, up[MicrosoftUserProfiles.PropertyConstants.LastName].Value as string, up[MicrosoftUserProfiles.PropertyConstants.Department].Value as string, up[MicrosoftUserProfiles.PropertyConstants.WorkPhone].Value as string);

                }
                profileGrid.PageIndexChanging += new GridViewPageEventHandler(profileGrid_PageIndexChanging);
                Controls.Add(profileGrid);
                pcb.BindGrid(profileGrid);
                base.Controls.Add(profileGrid);
            }

        }


         /// <summary>
        /// pagination Event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void profileGrid_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            profileGrid.PageIndex = e.NewPageIndex;
            pcb.BindGrid(profileGrid);
        }



As I think this is the most important function, when we talk about user-profile programming sector. I have used different approach to search users and try to exceed the performance level and also reduce the resource usage. we can discuss it in Line by Line section.

Line by Line :
  1. but  MicrosoftUserProfiles.ProfileBase[] searchResults = upm.Search(searchPattern); One way to search user according to the given keyword is , to get all users and iterate one by one and check for correct user who match with search scenario as following.                                                                            foreach (UserProfile profile in profileManager)

  1. {
         /// Add search criteria
    
     }                                                                                                    but when you go with this approach. you'll find that it take long time and more processing resources specially if you are iterating more than 10,000 profiles and it could be 100,000 who knows :) .                                                                                                                                                but profile manage gives us a one efficient way to search user only through it's User ID.  so we cannot use it with different keywords.  that's why I use MicrosoftUserProfiles.ProfileBase[]  which can hold the profile base objects that taken from . search method. as follow  upm.Search(searchPattern);                                              
  2. then you can iterate profile base object which only holds only search results. but you need to keep one thing in you mind you don't have all the detail regarding one user in a MicrosoftUserProfiles.ProfileBase object, as you do in MicrosoftUserProfiles.UserProfile Object, but you can get User ID from Profile base object. so using following iteration pattern you can take required user details.                                                                                         foreach (MicrosoftUserProfiles.ProfileBase profileTemp in searchResults)                {                                                                                                         // this loop will execute only for result not for it will not itrate through all User                    //Profile data set which taken by User Profile Manager                                                                       MicrosoftUserProfiles.UserProfile up = upm.GetUserProfile(profileTemp.ID);






I have create separate class called PropertyCollectionBinder to bind Data and create SP grid view. 

Property binder Class : 

using System;
using System.Web;
using System.Web.UI;
using System.Data;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using MicrosoftUserProfiles = Microsoft.Office.Server.UserProfiles;
using Microsoft.Office.Server;
using Microsoft.SharePoint.WebControls;
using System.Runtime.InteropServices;
using System.Xml.Serialization;

namespace SearchWebPartTest
{
    public class PropertyCollectionBinder
    {
        protected DataTable PropertyCollection = new DataTable();
        protected DataView PropertyView = new DataView();
        protected SPGridView grid = new SPGridView();
        public PropertyCollectionBinder()
        {
            PropertyCollection.Columns.Add("AccountName", typeof(string));
            PropertyCollection.Columns.Add("FirstName", typeof(string));
            PropertyCollection.Columns.Add("LastName", typeof(string));
            PropertyCollection.Columns.Add("Department", typeof(string));
            PropertyCollection.Columns.Add("WorkPhone", typeof(string));
        }
        public void AddProperty(string AccountName, string FirstName, string LastName, string Department, string WorkPhone)
        {
            DataRow newRow = PropertyCollection.Rows.Add();
            newRow["AccountName"] = AccountName;
            newRow["FirstName"] = FirstName;
            newRow["LastName"] = LastName;
            newRow["Department"] = Department;
            newRow["WorkPhone"] = WorkPhone;
        }
        public void BindGrid(SPGridView grid)
        {
            BoundField fldAccountName = new BoundField();
            fldAccountName.HeaderText = "Name";
            fldAccountName.DataField = "AccountName";
            fldAccountName.HtmlEncode = false;
            grid.Columns.Add(fldAccountName);

            SPBoundField fldFirstName = new SPBoundField();
            fldFirstName.HeaderText = "First Name";
            fldFirstName.DataField = "FirstName";
            grid.Columns.Add(fldFirstName);

            SPBoundField fldLastName = new SPBoundField();
            fldLastName.HeaderText = "Last Name";
            fldLastName.DataField = "LastName";
            grid.Columns.Add(fldLastName);

            SPBoundField fldDepartment = new SPBoundField();
            fldDepartment.HeaderText = "Department";
            fldDepartment.DataField = "Department";
            grid.Columns.Add(fldDepartment);

            SPBoundField fldWorkPhone = new SPBoundField();
            fldWorkPhone.HeaderText = "Ext";
            fldWorkPhone.DataField = "WorkPhone";
            grid.Columns.Add(fldWorkPhone);

            //PropertyCollection.DefaultView.Sort = "WorkPhone asc";
            PropertyView = new DataView(PropertyCollection);
            grid.DataSource = PropertyView;
            grid.Width = 500;
            grid.EnableViewState = true;
            grid.PageSize = 10;
            grid.AllowPaging = true;
            grid.PagerTemplate = null;
            grid.AutoGenerateColumns = false;
            grid.DataBind();
        }


    }
  
}




Ex: when we search users who belongs to the “ENGRG SRVCS” .


 And when you search through First or Last Name “thilina”



ok That's It ... 
HAPPY CODING

No comments:

Post a Comment