Sunday 17 February 2013

Read AD Group from People Picker field, Get users of corresponding Group from AD & add them in other People Picker field of Library/List in SharePoint 2010



In SharePoint we can validate users using People Picker functionality. We can create a column with type as Person or Group which will provide us to validate users or groups. 

Now I have a requirement that user should be able to share particular documents with specific Users without breaking the inheritance every time. To achieve this I created a column “Shared Members” with column type as People or Group. Now the user can search & add the users in this column. Also in the view of this library I have applied a filter to show the documents only if “Created By= [Me]” or “Shared Members = [Me]”. This filter will display only those documents to the user if the document is created by him or he is present in the Shared Members column. 

Now here the challenge I was facing is if User wants to share the document with specific AD Group, he will add the group in the Shared Members column. But in this case the filter does not work as the SharePoint does not read users from that group. Hence to get all the users from the group I have fired an Event Receiver on Event Updated as it is a document library. 

Now I will create another column same as “Shared Members” & name it as “All Shared Members”.
In this Event Receiver we will read the AD Group from the “Shared Members“ column, get all the users of that group from AD using LDAP connection & store these users in the “All Shared Members” column.
Now I will change the column in filter & filter the documents based on “Created By” & “All Shared Members”.

Below are the steps to create the Event Receiver

  1. Open Visual Studio & Select Event Receiver & give proper Name.
   2.  After giving the Proper Name to the Project, the next screen appears asking to deploy the solution as Sandboxed or Farm level. Select Deploy as Farm Solution
    3.  The Next Popup will provide to choose the Event Receiver Settings. Here in the Type of Event Receiver we will select “List Item Event” as I have to fire the Event Receiver on each item. Then select the “Document Library” as the Event Source & finally the when the event is to be fired, here select “An item was updated” as it is a document library.
    If we want to achieve this functionality “List” then we need to fire the Event Receiver on “An Item was Added” as it is a list. Click Finish.
    4.  The Default solution will look as below
     5.  The default code in the Event receiver file will be as below
    6.  Now in the ManageSharedMembers.cs file add the below code.

    public class ManageSharedMembers : SPItemEventReceiver
{

    private string listname = "";
    //Give Shared Members Column Name
    private string SharedMembers = ConfigurationManager.AppSettings["DocumentSharedMembers"];
    //Give All Shared Members Column Name
    private string DestinationSharedMembers = ConfigurationManager.AppSettings["DocumentDestinationSharedMembers"];
   /// <summary>
   /// An item was updated.
   /// </summary>
   public override void ItemUpdated(SPItemEventProperties properties)
   {
    listname = properties.ListTitle.ToString();
    //Disable Event Firing as we are updating the item
    this.EventFiringEnabled = false;
    try
    {
     SPSecurity.RunWithElevatedPrivileges(delegate()
     {
      //Get current item
      SPListItem currentitem = properties.ListItem;
      //Check for the Shared Members & All Shared Members fields are present or not
    if (properties.ListItem.Fields.ContainsField(SharedMembers) && properties.ListItem.Fields.ContainsField(DestinationSharedMembers))
    {
     properties.Web.Site.AllowUnsafeUpdates = true;

     //Check whether the Shared Members column contains value or not.
     //If the event receiver is fired on List then in the if condition check the shared members column for empty or not as below commented
     Properties.AfterProperties[SharedMembers].ToString()!=string.Empty
     If it is on document library then as shown in below if condition

     if (currentitem.Properties[SharedMembers].ToString() != string.Empty)
     {
      string fieldValue = currentitem[SharedMembers].ToString();
      SPFieldUserValueCollection users = new SPFieldUserValueCollection(currentitem.Web, fieldValue);
      SPFieldUserValueCollection user = new SPFieldUserValueCollection();
      //Create LDAP connection with the Active Directory Server
      DirectoryEntry de = new DirectoryEntry();
      de.Path = "LDAP://Network IP/DC=sharepoint,DC=com";
      de.AuthenticationType = AuthenticationTypes.Secure;
      //Read users one by one to check for any groups present
      for (int i = 0; i < users.Count; i++)
      {
       SPFieldUserValue singlevalue = users[i];
       SPUser singleuser = singlevalue.User;
       string groupname = singleuser.Name.ToString();
       //Check whether the given value is user or group
       if (singlevalue.User.IsDomainGroup)
       {
        //If given value is a group then get all users from AD of that group
        DirectorySearcher searcher = new DirectorySearcher();
        searcher.Filter = ("(&(objectClass=group)(CN=" + groupname + "))");
        SearchResult result = searcher.FindOne();
        string username;
        if (result != null)
        {
         DirectoryEntry deGroup = new DirectoryEntry(result.Path);
         PropertyCollection pcoll = deGroup.Properties;
         try
         {
          //Fetch the users from the AD and add in the SPFieldUserValueCollection
          foreach (object obj in deGroup.Properties["member"])
          {
           username = obj.ToString();
           char[] split1 = { ',' };
           string[] getname = username.Split(split1);
           string temp = getname[0];
           char[] split2 = { '=' };
           string[] getname2 = temp.Split(split2);
           username = getname2[1];
           SPUser uservalue = currentitem.Web.EnsureUser(username);
           user.Add(new SPFieldUserValue(currentitem.Web, uservalue.ID, uservalue.Name));
          }
         }
         catch (Exception)
         {

         }
        }
       }
       else
       {
        //if singlevalue is user then you can use all SPUser properties & add.
        SPUser userdetails = singlevalue.User;
        user.Add(new SPFieldUserValue(currentitem.Web, userdetails.ID, userdetails.Name));
       
       }
      }
      //update all these users in the All Shared Members column.
      currentitem[DestinationSharedMembers] = user;
      currentitem.Update();
      //After updating the item now enable the Event Firing
      this.EventFiringEnabled = true;
     }
    }
    //}
   });
  }
  catch (Exception)
  {

  }
  base.ItemUpdated(properties);
 }
}
         Now Build & deploy the solution in the SharePoint Web Application.
       
       When this Event Receiver is fired, it will check for any groups in the “Shared Members” columns & then fetch the corresponding users from the AD & store them in the other column i.e. “All Shared Members”.

1 comment:

  1. Hi, nice article. How you configure sharepoint list fields? Yo define this fields as person group with chose from "All users" marked as true?

    ReplyDelete