Friday, October 21, 2011

Event Receivers Issue After Migration From SharePoint 2007 to SharePoint 2010

We have a SharePoint 2007 site created by Reservations Template (part of WSS 3.0 Application Templates). The site is used for company-wide meeting room booking. After migrating to SharePoint 2010 (database-attachment approach) the room-booking system was not working properly. Same resource can be doubly booked and sometimes you can't book some resources while they show as available in the UI.

After some digging I found the problem was caused by the Event Receiver associated with the Reservations List. Originally in SharePoint 2007 the Reservations List has registered the Event Receivers with assembly of "ReservationEventHandler, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c". That assembly registration became "ReservationEventHandler, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" after migration for some reason. To fix the problem, we simply correct the List's event registry:
static void FixReservationEventReceivers(SPSite site, string webUrl, string listName)
{
    using (SPWeb web = site.OpenWeb(webUrl))
    {
        bool hasAddingEvent = false, hasDeletingEvent = false, hasUpdatingEvent = false;
        SPList list = web.Lists.TryGetList(listName);
        List<SPEventReceiverDefinition> invalidReceivers = new List<SPEventReceiverDefinition>();
        foreach (SPEventReceiverDefinition item in list.EventReceivers)
        {
            if (item.Assembly.Contains("ReservationEventHandler") && item.Assembly.Contains("Version=14.0.0.0"))
                invalidReceivers.Add(item);
            if (item.Assembly.Contains("ReservationEventHandler") && item.Type == SPEventReceiverType.ItemAdding)
                hasAddingEvent = true;
            if (item.Assembly.Contains("ReservationEventHandler") && item.Type == SPEventReceiverType.ItemDeleting)
                hasDeletingEvent = true;
            if (item.Assembly.Contains("ReservationEventHandler") && item.Type == SPEventReceiverType.ItemUpdating)
                hasUpdatingEvent = true;
        }
        foreach (var item in invalidReceivers)
        {
            item.Delete();
        }

        string assemblyName = "ReservationEventHandler, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c";
        string className = "Microsoft.SharePoint.ApplicationTemplates.ReservationEventHandler";
        if (!hasAddingEvent)
            list.EventReceivers.Add(SPEventReceiverType.ItemAdding, assemblyName, className);
        if (!hasDeletingEvent)
            list.EventReceivers.Add(SPEventReceiverType.ItemDeleting, assemblyName, className);
        if (!hasUpdatingEvent)
            list.EventReceivers.Add(SPEventReceiverType.ItemUpdating, assemblyName, className);
    }
}
You may wonder what those event receivers do with the List item. The explanation is lengthy but not worthy knowing to be honest. The template was not well designed and implemented in my opinion. I spent quite a bit of time to customize and optimize the template. Actually we don't need those event receivers anymore after my modification and the performance of the booking system has been improved significantly since then (hundreds of thousands of records in our Reservations List). I may write some notes about that later.