Event Receivers

An event receiver in Microsoft SharePoint Foundation 2010 is simply a method that is called when a triggering action occurs on a specified SharePoint object. Triggering events include actions such as adding, updating, deleting, moving, checking in, and checking out. SharePoint objects that listen for events—that is, event receiver hosts—include objects such as site collections, sites, lists, and workflows.

 

Events are valuable tools for SharePoint developers. When a user performs an action that affects a SharePoint site, you can trap that action and respond to it with custom code. For example, if a project manager needs to be alerted when new documents or files are added to a given document library, you could write event receiver code to send an e-mail notification to the project manager, and then bind that code to the item-addition action on the document library. SharePoint Foundation 2010 provides enormous flexibility for detecting and responding to SharePoint events.

 

 

There are two type of SharePoint events:

  • Asynchronous (After) events

    Synchronous events, e.g. are: ItemAdding, FieldUpdating, FeatureDeactivating etc… (like all those events that are having “-ing” as suffix).

 

  • Synchronous (Before) events
    Asynchronous events, e.g. are: ItemAdded, FieldUpdated, FeatureActivated etc… (like all those events that are having “-ed” as suffix).

lists the event receiver base classes as well as the event host types that support each receiver, along with the events they support.

  Event receiver base class Available event host types Supported events
  SPWebEventReceiver ·     SPSite

·     SPWeb

·     SiteDeleting

·     SiteDeleted

·     WebAdding

·     WebProvisioned

·     WebDeleting

·     WebDeleted

·     WebMoving

·     WebMoved

  SPListEventReceiver (lists) ·     SPSite

·     SPWeb

·     ListAdding

·     ListAdded

·     ListDeleting

·     ListDeleted

  SPListEventReceiver (fields) ·     SPSite

·     SPWeb

·     SPList

·     SPContentType

·     FieldAdding

·     FieldAdded

·     FieldDeleting

·     FieldDeleted

·     FieldUpdating

·     FieldUpdated

SPItemEventReceiver ·     SPSite

·     SPWeb

·     SPList

·     SPContentType

·     ItemAdding

·     ItemAdded

·     ItemDeleting

·     ItemDeleted

·     ItemUpdating

·     ItemUpdated

·     ItemFileConverted

·     ItemFileMoving

·     ItemFileMoved

·     ItemCheckingIn

·     ItemCheckedIn

·     ItemCheckingOut

·     ItemCheckedOut

·     ItemAttachmentAdding

·     ItemAttachmentAdded

·     ItemAttachmentDeleting

·     ItemAttachmentDeleted

  SPEmailEventReceiver ·     SPSite

·     SPWeb

·     SPList

·     EmailReceived
  SPWorkflowEventReceiver ·     SPSite

·     SPWeb

·     SPList

·     SPContentType

·     WorkflowStarting

·     WorkflowStarted

·     WorkflowCompleted

·     WorkflowPostponed

 

AfterProperties and BeforeProperties are concerned for any event, they can help you to extract After and Before change in state about the object in context. This case is true and valid for any document library in context. For example, if you want to prevent any change in particular column of Document library your code must be:
public override void  ItemUpdating(SPItemEventProperties properties)

{

if (properties.BeforeProperties[“column”] != properties.AfterProperties[“column”])

{

properties.Cancel = true;

properties.ErrorMessage = “This column cannot be changed”;

}

}

But such examples are only valid for Document Library in context, as per the Microsoft; as it is written inSDK that “For documents, Before and After properties are guaranteed for post events, such as ItemUpdated, but Before properties are not available for post events on list items”. So, statement written like these form the basis of analysis, on testing various events during Addition, Deletion and Update  of both SharePoint lists and SharePoint library,

here is the conclusion that is actually drawn for any List:

List BeforeProperties AfterProperties properties.ListItem
ItemAdding No value New value Null
ItemAdded No value New value New value
ItemUpdating No value Changed value Original value
ItemUpdated No value Changed value Changed value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null

 

No value means that column value in the hash table was not available.
New value means that the correct value for the column was available.
Changed value means that the correct updated value was available.
Original value means that the correct original value was available.

Here is the results on any document library:

Library BeforeProperties AfterProperties properties.ListItem
ItemAdding No value No value Null
ItemAdded No value No value New value
ItemUpdating Original value Changed value Original value
ItemUpdated Original value Changed value Changed value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null

Properties.ListItem refers the the current value for the list item at that point in the event.  Null means that the item is not available.

Some noteworthy points are:

  • Not surprisingly, we get null values for for ItemAdding (before item is added) and ItemDeleted (after item is deleted).
  • As correctly documented in the SDK, item events for lists do not expose BeforeProperties.
  • ItemAdding and ItemAdded correctly report the value in the AfterProperties for an list item, but not a library item.  This is curious.
  • We have no visibility on the previous states during the ItemDeleted event.  Once it’s deleted, it’s clearly gone.

So, if we go back to our original problem listed above.  How can we prevent a user from changing a certain column for an item in a list event?  From the list table, you can see if we hook into the ItemUpdating event, we can compare the current item’s value (properties.ListItem) to the AfterProperties value.  The code would look like this:

 

if (properties.ListItem[“column”] != properties.AfterProperties[“column”])

{

properties.Cancel = true;

properties.ErrorMessage = “This column cannot be changed”;

}

Note : For good looking errors you can redirect user to custom error page (which you have to create)

properties.Cancel = trueproperties.Status = SPEventReceiverStatus.CancelWithRedirectUrl; properties.RedirectUrl = “/_layouts/MySolution/CustomErrorPage.aspx?Error=” + errorMessage;

 

 

Bad Coding Practice

Instantiating an SPSite object inside an event receiver

public override void ItemDeleting(SPItemEventProperties properties)

{

using (SPSite site = new SPSite(properties.WebUrl))

{

using (SPWeb web = site.OpenWeb())

{

SPList list = web.Lists[properties.ListId];

SPListItem item = list.GetItemByUniqueId(properties.ListItemId);

// Operate on an item.

}

}

}

 

Good Coding Practice

Using SPItemEventProperties

// Retrieve SPWeb and SPListItem from SPItemEventProperties instead of

// from a new instance of SPSite.

SPWeb web = properties.OpenWeb();

// Operate on the SPWeb object.

SPListItem item = properties.ListItem;

// Operate on an item.

 

Advertisements