Karine Bosch’s Blog

On SharePoint

SharePoint Event Receivers


In SharePoint you can add event handlers to the different lists, document libraries and content types within a SharePoint site. Event handlers are defined in custom .NET assemblies. You can define event handlers for the different operations on list items, like adding a list item, updating a list item or deleting a list item.

Event handlers need to be registered and can best be installed and registered through the SharePoint feature framework.

Synchronous and Asynchronous Events

There are synchronous and asynchronous events. Events ending by –ing are synchronous events: ItemAdding, ItemUpdating, ItemDeleting. Event handlers defined for these events are executed before the operation is executed on the content database. Asynchronous events are the events that end by –ed: ItemAdded, ItemUpdated, ItemDeleted. Event handlers for these events are executed after the operation is occurs in the content database.

Base Classes

There are different base classes from which you can inherit when developing event handlers. The decision from which class you are going to inherit depends on what you want to achieve with your event handler:

  •  SPItemEventReceiver: inherit from this class if you want your event handler to be executed when a list item is added, updated or deleted.
  •  SPListEventReceiver: inherit from this class if you want your event handler to be executed when the structure of your list is modified or when a content type is added or removed from the list.
  •  SPFeatureEventReceiver: you can add an event handlers to a feature events like activation and deactivation, installation and deinstallation.
  •  SPEmailEventReceiver: you can also develop an event handler for emails that are sent to a SharePoint list.
  •  SPWebEventReceiver: you can also handle events that occur when a site is added to or removed from a site collection.

Updating the list item

There are 3 methods to update a list item:

  • Update: With this method you can update the list item. But it also changes the Modified By column (internal name Editor) to the SHAREPOINT\system account and sets the Modified column to the current date time. If versioning is enabled, the version is increased.
  • SystemUpdate: This method also updates the list item but preserves the values in the Modified By column (internal name Editor) and the Modified column. This method comes with two overloads. You can also specify a boolean value to indicate if you want to increase the version number or not.

systemupdate

 

·         UpdateOverwriteVersion: This method updates the list item without changing the version number. It also allows to modifiy the values in the system columns lik Created By (internal name Author), Modified By (internal name Editor), Modified and Created.

Disabling and Enabling the event handler

To avoid that a list item event handler is triggered again and again and again, you have to prevent the event handler from firing before you update changes to the list item. You can achieve this by executing the DisableEventFiring method on the list item. After the changes are saved you can activate the event handler again by executing the EnableEventFiring method on the list item.

Best practice is to execute the DisableEventFiring method right before any of the update methods and to execute the EnableEventFiring method right after one of the update methods. 

AllowUnsafeUpdate

AllowUnsafeUpdate is a property on the SPSite and SPWeb objects. You can set it to true to avoid security validation before the changes are written to the content database. There is an excellent and very detailed post about this property.

RunWithElevatedPermissions

You will find a lot of code snippets wrapped in a RunWithElevatedPermissions construct. This is necessary if you will be changing data that is not accessible by some types of users. For example if you need to update a column or another list when a document or list item is read, this will cause en error when the user has only read access to this list or the other list. In that case you can wrap your update code in the following construct:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPWeb web = properties.OpenWeb())
    {

      // web will be based on the rights for the system account
     // here follows your event handler code

    }

});

 

21 Comments »

  1. Thanks for the great article, it answered a lot of questions for me. I am looking for a what to update all the other colums based on the column bieng added or changed. for instance if I had a column with
    Order Planer
    1 = Mercury
    2 = Venus
    3 = Mars

    Then somoone added earh as 3 then I would want the list to be

    1 = Mercury
    2 = Venus
    3 = Earth
    4 = Mars

    I am sure the example you give has most of what I need, but I am not experienced enough to see the update to every column change.

    Do you have anyplace you can point me to for this.

    Thanks,

    Paul

    Comment by Paul | April 20, 2009 | Reply

  2. how can i create the feature.xml,elements.xml and install.bat and how to add it to the project… Please help me to do this.

    Comment by sanu | April 27, 2009 | Reply

  3. euh…. it’s explained in the post in steps 4 to 6

    Comment by Karine | April 27, 2009 | Reply

  4. Paul,
    Sorry for the late reply but I found your comment in the spam folder.
    I’m not sure if I understand your question well, but if you want to change the order in which the list items are listed, you have perhaps to change the view: you can change the order in the Order By section so that the list view sorts on the column Order Planet.
    Karine

    Comment by Karine Bosch | May 21, 2009 | Reply

  5. Hi Karine.

    I’ve read that code ListTemplateID=”100″ is for Generic Lists. I’m wondering if all kinds of lists will trigger this event?

    Regards,
    Gabriel

    Comment by Gabriel | July 22, 2009 | Reply

  6. Hi Gabriel,
    Using ListTemplateID=100 attaches the event handler to all lists of type Generic List.
    Specifying ListTemplateID=101 will attach the event handler to a document library.
    Greetz,
    Karine

    Comment by Karine | July 22, 2009 | Reply

  7. Hi Karine,

    Your knowledge in SharePoint is tremendous. I am a regular reader of your blog.

    Thanks
    Prashanth

    Comment by Prashanth Kumar | August 27, 2009 | Reply

  8. Karin,

    Thanks a lot for sharing your knowledge.
    As a novice in MOSS development, your knowledge is precious for me.
    I created an EventReceiver based on your examples… with success 😉
    But I have a problem… Using a custom list and an EventReceiver of type “ItemUpdating”, it seems to be impossible to catch the “BeforeProperties” of the ListItem… Do you confirm that it’s impossible ?
    My goal, prevent that a user can modify a specific field…

    Thanks for your help…

    Steve

    Comment by Steve | September 25, 2009 | Reply

  9. Hi Steve,
    I confirm that the BeforeProperties doesn’t work with ItemUpdating. You could retrieve the current values from the properties.ListItem:

    string country_before = properties.ListItem[“WorkCountry”].
    ToString().ToUpper();
    string country_after = properties.AfterProperties
    [“WorkCountry”].ToString().ToUpper();

    if (country_before != country_after)
    {
    }

    Does this work out for you?
    Anyway, I’ll make a walkthrough for this 😉
    Karine

    Comment by Karine Bosch | September 26, 2009 | Reply

  10. Thanks again for your answer, Karine…
    It works perfectly.

    Anyway, I have still another question.
    From the Event Receiver I created, I’m trying to call a WCF WebService. I know my WCF is working with a Silverlight application, but not in my Event Receiver.
    I receive the following answer : “Could not find default endpoint element that references contract ‘PamelaWCF.IPamelaServices’ in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.”
    Is it impossible to call a WCF from an Event Receiver ? At what have I to be attentive ?

    Thanks for your help…

    PS : I saw the Walkthroughs #4… 😉

    Comment by Steve | September 28, 2009 | Reply

  11. Steve,
    I’m pretty sure it is possible to call a method of a WCF service asynchronously from within an event handler. I’ll test it out myself one of the coming days. But at the moment I’m not able to tell you exactly where to look.
    Perhaps you can start reading here (http://blah.winsmarts.com/2008-5-SharePoint_as_a_WCF_Host.aspx) and perhaps Sahil Malik is able to help you out on this.
    Karine

    Comment by Karine Bosch | September 28, 2009 | Reply

  12. Karine,
    I found a workaround.
    I used my WCF through a “Service Reference” and it didn’t work.
    Now, I’m using it through “Web Reference”… And it’s working !
    Thanks again for your help…
    Steve

    Comment by Steve | September 28, 2009 | Reply

  13. hi,

    i have a news site (variation implemented). i want to capture page update event as i have to send the same content with some addtions to different email addresses when the page is published.

    the problem is that i am not able to capture event any event of those news pages while able to capture events of other lists. i have set ListTemplateId=”101″.

    any clue

    Comment by mohsin | November 10, 2009 | Reply

  14. […] I’m saying the same as Karine Bosch. Just found it while searching for error […]

    Pingback by The trouble with editing items on synchronous add-events « SharePoint 2007 Hut | August 10, 2010 | Reply

  15. hi when i added document programatically my itemAdded event reciver is not firing ?If i change in Synchronous in Element.xml its firing why?itemAdded is asynchronous event then why i need to fire synchronous?pls help me

    Comment by Vijay Hole | January 31, 2013 | Reply

    • Hi Vijay,
      If you’re elements.xml is ok, that’s already a good start. Is you’re event handler really attached to the list? You can check this with SharePoint Manager (free community tool you can download). If so, can you try to place a breakpoint within your event handler and attach the debugger? Perhaps your event handler fires but there is an error in the code?
      Karine

      Comment by Karine Bosch | February 1, 2013 | Reply

  16. In my tests the web will not be based on the rights of the system account when I use properties.OpenWeb()

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
    using (SPWeb web = properties.OpenWeb())

    Instead i tried the following and that worked for me:

    Guid siteId = properties.SiteId;
    Guid webId = properties.Web.ID;

    SPSecurity.RunWithElevatedPrivileges(delegate
    {
    using (SPSite site = new SPSite(siteId))
    {
    using (SPWeb web = site.OpenWeb(webId))
    {
    // web will be based on the rights for the system account

    Comment by Erik | February 19, 2014 | Reply

  17. no this from above work with me
    ————————————————————————block of code————————–
    private void GetCurrentUserID(SPItemEventProperties properties)
    {

    //listID = properties.ListId;
    //itemID = properties.ListItem.UniqueId;
    //siteID = properties.SiteId;
    base.EventFiringEnabled = false;
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
    using (SPSite XSite = new SPSite(properties.SiteId))
    {
    //using (SPWeb XWeb = XSite.OpenWeb())
    //using (SPWeb XWeb = properties.OpenWeb())
    using (SPWeb XWeb = XSite.OpenWeb(properties.Web.ID))
    {
    XWeb.AllowUnsafeUpdates = true;

    SPList XList = XWeb.Lists[properties.ListId];
    //SPListItem item = XList.Items[properties.ListItem.UniqueId];
    SPListItem item = XList.Items.GetItemById(properties.ListItem.ID);
    item[“WidAuthUserID”] = 111;
    XList.Update();

    XWeb.AllowUnsafeUpdates = false;

    //string myFieldValue = (string)properties.ListItem[“MyField”];

    #region Update existing record
    //XWeb.AllowUnsafeUpdates = true;

    //SPListItem item = XList.GetItemById(int.Parse(DTHDSettings.Rows[0][System.Configuration.ConfigurationManager.AppSettings[“PortalSettingsListIDField”].ToString()].ToString()));
    //item[System.Configuration.ConfigurationManager.AppSettings[“PortalSettingsListValueField”].ToString()] = “true”;
    //XList.Update();

    //XWeb.AllowUnsafeUpdates = false;
    #endregion
    }
    }

    });
    base.EventFiringEnabled = true;
    //string xxxx = properties.ListId.ToString();
    //xxxx = properties.ListItemId.ToString();
    //xxxx = properties.ListTitle.ToString();
    //SPListItem NewItem = properties.ListItem;

    //SPList Xlist = properties.List;

    //this.EventFiringEnabled = false;
    //NewItem[“WidAuthUserID”] = 111;
    //NewItem.Update();
    //this.EventFiringEnabled = true;

    //EventLog.WriteEntry(“SWCC_Emp Engagment Event Reciver”, String.Concat(” “, WareHousesList_Name, ” for warehouses list named “, WarehousesList, ” in web site “, Settings.SharePointSite, ” is not exist”));
    //properties.List
    //SPUser user = XWeb.SiteUsers[loginName];

    }
    ——————————————————————————————————————————-

    any help

    Comment by osama | December 7, 2015 | Reply

  18. sorry for Disturbing you, i got my stupid mistake.
    its item.Update(); instead of XList.Update();
    sorry again 🙂

    Comment by osama | December 7, 2015 | Reply

  19. This is the best and most simplified post on event receiver topic ! Thanks

    Comment by snhthakare | March 9, 2016 | Reply

  20. Timer job inserts list items into a list. List has an Event Receiver. For some, not all, list items, the event receiver throws and exception. The exception is that the item was updated by a different user, click back in the browser. Timer service identity and web application pool identity are different.

    Comment by Daren Caywood | June 18, 2017 | Reply


Leave a reply to sanu Cancel reply