Resolve issues while updating People Picker Column of a List in Event Handler

Let’s say, you have a List with a People Picker column (Person or Group) on your site. Now, you need to add an event handler for new item add/update. Normally, if you go by the conventional way, you would get the following error:

Invalid data has been used to update the list item . The field you are trying to update may be read only.

I tried to figure out what exactly caused this error while I trying to set a people picker column property in my event handler programmatically. Afterwards, I found out that People Picker Column in a List is a read-only field. By Default, the read-only mode of this field remains true while we try to add/update it for a list item. So, how to overcome this problem? Well, it’s not that difficult. You just need to set the read-only mode of the people picker column to be “False” at first and after that,  update the property of the people picker. After finishing everything, set the read-only mode of the field again to “True”. Here is an example how you can achieve this:


using (SPSite mySite = new SPSite(properties.SiteId))
 {
 using (SPWeb myWeb = mySite.OpenWeb(properties.RelativeWebUrl))
 {
 SPList currentList = myWeb.Lists[properties.ListId];
 SPListItem currentitem = currentList.GetItemById(properties.ListItem.ID);

 myWeb.AllowUnsafeUpdates = true;
 ServerContext ospServerContext = ServerContext.GetContext(mySite);

//Create a new UserProfileManager
 UserProfileManager pManager = new UserProfileManager(ospServerContext);

//Get the User Profile for the current user
 UserProfile uProfile = pManager.GetUserProfile(currentitem["Title"].ToString());

 //Set the read only mode of people picker column to FALSE
 currentitem.Fields["Direct Supervisor"].ReadOnlyField = false;

 if (uProfile["Manager"].Value != null)
 {
 string temp = @""+uProfile["Manager"].Value.ToString();
 string temp1=temp.Replace("\\",@"\");
 //Setting the property of people picker column
 currentitem["Direct Supervisor"] = myWeb.AllUsers[temp1].ID;

 }

//Update List Item
 currentitem.Update();
 //Update List
 currentList.Update();

//Set the read only mode to TRUE
 currentitem.Fields["Direct Supervisor"].ReadOnlyField = true;

//Update the List item again
 currentitem.Update();
 //update the List again
 currentList.Update();

}
}

Inside the above code, you can see that first of all, I set the property of current site’s allowUnsafeUpdates to True which will allow you to change the read-only mode of a field. I have used the User Profile service to set the value of People Picker Control (in this case, the field name is “Direct Supervisor”). After setting the value of the field, I updated the List item and the list before changing back the read-only mode to be “True” again. Afterwards, I updated the current item and current list once again which ensures that the update will take place without any such error which happened previously.


			

How to create Dynamic Column in a List Event Receiver & set the Column Name with a Dynamic Value and set Value of that Column for Current List item?

Few days ago, I was working on a List where the necessity of creating dynamic column raised. Also, the need to initiate the column name inside an event receiver and setting the value of the newly column for the current item were needed. So, I created a custom (demo) List which is named as “DemoProjects”.

I created the following columns:

Title, Description, Comments, RadComments (for checking the event)

I needed the column to be created for an existing List item. So, I created a new item like the following keeping “Comments” and “RadComments” blank.

image

image

Now, in order to create the event receiver I created a new project of “Event Receiver” type in Visual Studio 2010.

I set the “ItemUpdated” method to True as I need to create the column while updating the list item.

image

After that, Visual Studio automatically creates the method name and parameters for ItemUpdated method

 public override void ItemUpdated(SPItemEventProperties properties)
 {
    base.ItemUpdated(properties);
 }

Now, this base.ItemUpdated runs will run for each custom list. In order to attain my objective, I have modified this method to the following: ( I have tried to clarify all the steps by commenting each line of code )

  1. public override void ItemUpdated(SPItemEventProperties properties)
  2.        {
  3.            if (properties.ListTitle == “DemoProjects”)
  4.            {
  5.                string colComments = “”; // Column Display name
  6.                string colCommentsStr = “”;  //  Internal name of the Column name
  7.                string curUser = “”;  // Current user name
  8.                using (SPSite site1 = new SPSite(properties.SiteId)) //Accessing the current site with current user permission
  9.                {
  10.                    using (SPWeb web1 = site1.OpenWeb(properties.RelativeWebUrl))
  11.                    {
  12.                        curUser = web1.CurrentUser.Name.ToString();  // Getting the current user display name
  13.                    }
  14.                }
  15.                SPSecurity.RunWithElevatedPrivileges(delegate()  // To Elevate the permisson of the current user which runs as a system acc to create the list column
  16.                {
  17.                    using (SPSite site = new SPSite(properties.SiteId))
  18.                    {
  19.                        using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
  20.                        {
  21.                            EventFiringEnabled = false;   // Disabling the events firing to prevent unnecessary actions
  22.                            web.AllowUnsafeUpdates = true;  // To execute actions which are not permitted by default
  23.                            SPList radList = web.Lists[properties.ListId];  // Getting the current List
  24.                            SPListItem project = web.Lists[properties.ListId].GetItemById(properties.ListItem.ID); // Getting the Current List Item
  25.                            colComments = “Comments: “ + curUser; // Setting the column name with current user name
  26.                            if (!radList.Fields.ContainsField(colComments))
  27.                            {
  28.                                radList.Fields.Add(colComments, SPFieldType.Note, false); // Adding new column in current List
  29.                                radList.Update(); // Updating the current List after adding new column
  30.                                Guid guidViewID = radList.Views[“All Items”].ID; // Getting the Guid for “All items” view of current list
  31.                                SPView vw = radList.GetView(guidViewID);
  32.                                vw.ViewFields.Add(colComments);  // Adding the new column in All items view
  33.                                vw.Update();  // Updating the All items view
  34.                                project.Update(); // Updating the current List item
  35.                                base.ItemUpdated(properties);  // Attaching current event to current list item
  36.                                radList.Update();  // Updating the current list
  37.                            }
  38.                            colCommentsStr = radList.Fields[colComments].InternalName.ToString(); // Getting the internal name of newly created column
  39.                        }
  40.                    }
  41.                });
  42.                using (SPSite site2 = new SPSite(properties.SiteId))  // Again accessing the site with current user permission
  43.                {
  44.                    using (SPWeb web2 = site2.OpenWeb(properties.RelativeWebUrl))
  45.                    {
  46.                        SPListItem project1 = web2.Lists[properties.ListId].GetItemById(properties.ListItem.ID); // Getting current List item
  47.                        project1[colCommentsStr] = project1[“Comments”].ToString(); // Setting current item’s new column’s value to Comments column
  48.                        project1[“RadComments”] = “Done!”; // Settting RadComments column’s value to “Done”
  49.                        project1.Update();   // Updating the current list item
  50.                        web2.AllowUnsafeUpdates = false; // After completing the action setting unsafe updates to false
  51.                    }
  52.                }
  53.            }
  54.            EventFiringEnabled = true;  // Enabling event firing for user interaction
  55.            base.ItemUpdated(properties); // Attaching current event to current list item
  56.        }

Now, after deploying this Event Receiver, I edited the previously created new item.

image

Notice that, I kept “RadComment” blank and there are currently no other columns in this list except these four. So, what happened when I clicked “Save”.

See the following window:

image

So, my dynamic column got created now (Comments: Current User name) and the value is also set by the event receiver which made it possible to know who commented the item. Now, if another user edits this item, another “Comment: Username” will be automatically be created and thus I can track all the comments made by the item editors and find out what he commented for that item. That’s pretty cool, isn’t it? Enjoy!!