SharePoint Event Receiver ItemUpdated method fires twice

by Mark DiGiovanni

I ran into an issue with an Event Receiver that was deployed to a Document Center Site library. The requirement is pretty simple, when a document is added to the Documents library or an existing document is updated, create a task for someone to review the document's metadata.

Problem

The problem is that the ItemUpdated event in this custom Event Receiver will fire twice under certain circumstances--such as having require document checkout set on the Documents library. In my case, users do not load documents directly to the site. Documents are only added or updated in this library from the Content Organizer via a custom Event Receiver/OOTB Approval Workflow combo on multiple Document Center Workspaces--which exist in their own Site Collections.

I've done my due diligence and followed recommendations here and here. I made sure that the event receiver was not registered twice using the SharePoint 2010 Manager tool. I made sure to DisableEventFiring() before creating the task item. Regardless of what I tried, I really couldn't track down exactly why it was getting fired twice.

Solution

To work around this issue, I implemented the following code:

SPListItem item = properties.ListItem;

if (item != null)

{

SPPropertyBag currentBag = item.Web.Properties;

string docID = item["_dlc_DocId"].ToString();

if (currentBag.ContainsKey(docID) && currentBag[docID] != null)

{

currentBag[docID] = null;

currentBag.Update();

}

else

{

EventFiringEnabled = false;

CreateTask(properties);

currentBag.Add(docID, "added");

currentBag.Update();

 

this.EventFiringEnabled = true;

}

The code looks for the key (the Doc ID) in the property bag and if it is present, skip the creation of the task and remove the property from the bag. The document's Doc ID is being used as the key--it will be unique. It really doesn't matter what the value of the property is--it just matters that it is there. This could have been implemented using Session State, but this is not available in events ending with "ed" in Event Receivers and probably not the best option anyway for several reasons.

It is not enough to call the remove method like so:

currentBag.Remove(docID);

currentBag.Update();

This call will not necessarily remove the item from the bag--in my case it did not, however setting it to null will.  It is important to null out the item--if not, the size of the bag will keep growing.

References