Sunday, January 15, 2012

The importance of synchronous event handlers

In SharePoint, we can create list item event handlers (or receivers). I have written about this in the past, and even posted some code for setting the security automatically on a list item as it is created.
Now, there is one thing I wanted to write about this topic. Event handlers can be defined as either Synchronous or Asynchronous - regardless of the event type. By default, events were always asynchronous if they had the "ed" suffix (ItemAdded, ItemUpdated), and synchronous if they had the "ing" suffix (ItemAdding, ItemUpdating). However, sometimes we want to run our code in an "ed" event, but have it synchronous (notice that the opposite is impossible have the "ing" properties to run asynchronously)- for example, when we want to modify item properties when its added, but before the user has been redirected to a new page.
A classic example is the upload of a document to a document library. The user gets prompted to browse for a file and clicks upload. The next page would be the properties page for the file that was uploaded. If we want to set some of the properties to be pre-filled for the user, we have to do that after the file has been uploaded - but we cannot do that in ItemAdding, as at that point we don't have access to the item - it wasn't created yet. In ItemAdded we can set values to the item - but by default this event is asynchronous - and sharepoint will show the user the properties dialog while the event is still happening in the background. The result is disastrous : the user sees the properties screen, clicks "Save" and gets an error telling him or her that the item has been modified by another process or user.

To resolve this we use the "Synchronization" XML tag in the receiver's registration XML with the value set to "Synchronous" or, if the receiver is registered using server object model code, we set the "Synchronization" property of the receiver class to SPEventReceiverSynchronization.Synchronous. To quote MSDN: "Synchronous processing provides the ability to run the event in the same thread before sending the Web response back to the browser."

As an example, lets create an event receiver that sets the title of a file to the file name, as the file is being uploaded. The code is simple:

public override void ItemAdded(SPItemEventProperties properties)
           if (properties.ListItem["Title"] == null)
               int startingPoint = properties.AfterUrl.LastIndexOf("/");
               properties.ListItem["Title"] = properties.AfterUrl.Substring(startingPoint + 1);

Now, the XML that registers the receiver is :
<Receivers ListTemplateId="101">

Now, when uploading a file, the users are first asked for the file:
And when they upload, they see the dialog allowing them to change the file's name, and by magic the title is already filled for them!

Where can this be useful? I can think of a very real world example: assigning a number to a document as it is being uploaded. The title setting event can be critical in some scenarios where we have lists with lookup columns to a document library - since the lookup column cannot show the file name column we need to show the title, which means we cannot have an empty title (in which scenario you will also want to set the title to unique, and add extra code to make sure the title you are setting is not unique - dont assume that because it is a copy of the file name there wont be duplicates - remember that users may edit both file names and titles!).

Just in case someone finds this useful, I am uploading the code, and the compiled solution package to my company's web site as a free, open source solution for anyone to use on their own risk. I have tested this to work with Office365 (SharePoint online) and as a farm solution - so enjoy!. You can find all my company's free code samples and solutions in our document library on our web site. The specific files are: [Source Code] and [Sandbox Ready Package].

No comments: