IN THIS CHAPTER
One of the first facts that a SharePoint developer learns is that SharePoint is built on a foundation of lists. Virtually every piece of data contained within SharePoint is contained within a list of some form or another.
One of the extremely powerful new features in SharePoint is the ability to create event receivers for any list type. In previous versions of SharePoint, the only lists that had this functionality were document libraries, and even then the functionality was fairly limited.
An event receiver is a piece of managed code that is launched in response to an event that takes place within SharePoint. These events can be triggered in response to changes to list items, creation of new lists, new list items, list items being deleted, and much more. These event handlers can allow you to write extremely powerful applications that integrate directly with SharePoint lists.
This chapter shows you how to create event receivers as well as how to deploy them programmatically, via Features and via content types.
List event handlers are made possible through the concept of event receivers. An event receiver is a .NET Framework class, contained in a strong-typed Assembly that must be installed in the Global Assembly Cache (GAC). This class is then instantiated by SharePoint and when events for which the class has been registered are fired, event handlers on the event receiver class are then invoked.
This all works through the SPItemEventReceiver
class, which contains all of the plumbing necessary to subscribe and respond to list item events. Similarly, events on lists themselves are handled through the SPListEventReceiver
class. To create your own event receivers, you just need to create classes that derive from either the SPItemEventReceiver
class or the SPListEventReceiver
class. Both of these classes inherit from the abstract base class SPEventReceiverBase
.
In previous versions of SharePoint, the only way to create code that responded to events on lists was to create classes that implemented an interface. There were also problems in attempting to obtain a valid security context with which to access the SharePoint object model from inside an event handler. The worst part of SharePoint’s prior list event handling implementation is that it only allowed you to define event handlers for document libraries. No other list type within SharePoint supported managed code event handlers.
With the 2007 version of SharePoint, you create event receivers. These receivers are actually classes that derive from a base class. To write code that responds to a given event, you simply override the method on the base class that corresponds to the event for which your code will be listening.
Not only can you create event receivers for list items such as when an item changes or is created, but you can also create event receivers for lists, such as when list fields (columns) are added or removed.
The procedure for creating your own event receivers is a four-step process:
SPListEventReceiver
or from SPItemEventReceiver
.The following two sections illustrate how to create event receivers for lists and for list items. The final section of the chapter covers the process of deploying event receivers.
List events occur when the metadata of the list itself has been modified. For example, you can write code that will respond when fields are added to or removed from the list. As with most event receivers, you can create a handler either for the post event (occurs after the event has already taken place) or the during event (occurs before the event changes are made permanent).
Each list event receiver method takes a single argument of type SPListEventProperties
. This object allows your code to obtain information about the event, the context in which the event is executing, and allows you to optionally signal to SharePoint that the event should be canceled. Table 7.1 contains a list of the properties of this class.
Table 7.1. SPListEventProperties
Properties
Table 7.2 contains a list of events to which your code can respond.
To create a simple list event handler, start by creating a new class library in Visual Studio 2005. Right-click the project and select Properties. Click the Signing tab and select the <New...> option from the dropdown list for strong name keys and then fill out the Create Strong Name Key dialog box to sign the Assembly with a new key. You will see the new key (a file with the extension .snk
) appear in the solution.
Next, add a class to the class library called ListMetaLogger
. It should inherit from the base class SPListEventReceiver
.
Listing 7.1 shows a class that logs activity on list metadata to a text file on disk.
Listing 7.1. A Sample List Event Receiver Class
When deployed against a Task list (deployment of event receivers is covered later in this chapter) and a user adds a column to the list, the contents of listeventlog.txt
might look like this:
It is worth noting that the field name property is URL encoded. This means that when the user created a new field called “Test Column 2,” SharePoint converted the internal field name to Test_x0020_Column_x0020_2
. The spaces are converted into their hexadecimal equivalent: 0x0020.
Event receivers for list items work in exactly the same fashion as list event receivers. The only difference between the two is that the events and event properties with list item event receivers are related to list items and not list metadata.
Table 7.3 shows the list of properties available to event receivers when passed an instance of the SPItemEventProperties
class.
Table 7.3. SPItemEventProperties
Properties
Several more events are available for list items than for list metadata because there are far more significant events in the life cycle of list data than in list metadata. Table 7.4 contains a list of list item events to which your code can respond.
Listing 7.2 shows a sample class that logs item events to a text file.
Listing 7.2. Sample List Item Event Receiver
One aspect of list item event receivers (and to a lesser extent, list event receivers) that is extremely powerful is the ability to actually stop an event from taking place. If your code responds to the ItemUpdating
event and sets the Cancel
property of the properties
object to true
, the list item update will not take place. This allows you to custom code your own constraints on creating, updating, and deleting list items above and beyond what might be available natively within SharePoint.
So far, the sample code has just illustrated how to execute code unrelated to SharePoint (logging text information to disk) in response to an event. The vast majority of event receivers will also want to be able to access the SharePoint object model when handling an event. In addition to having access to the list item and the list when an item event occurs, you can also obtain a reference to the site collection in which the event occurred using the following code:
SPSite eventSite = new SPSite(properties.SiteId);
SPWeb eventWeb = eventSite.OpenWeb(properties.RelativeWebUrl);
With access to the SPSite
and SPWeb
instances for the website in which the event occurred, you can write code that performs more powerful actions. For example, you might want to create a new announcement every time a user creates a new entry in a given list. Using the previous two lines of code, you can obtain a reference to the Announcements list on the site and add new entries in the ItemAdded
event receiver method.
You can deploy event receivers in three different ways:
Regardless of how you deploy the event receivers, the class library that you created that contains the event receiver class must be strongly named (signed with a key) and must also be installed in the Global Assembly Cache (GAC).
If you want your event receivers to only be associated with a single instance of a list rather than with all lists of a certain template ID (Table 7.5 in the next section shows all the built-in template IDs), you can write some code to manually register your event receivers with a given list.
Table 7.5. Built-In SharePoint List Templates
The following code snippet shows how to associate an event receiver class and Assembly with a specific list by calling the Add
method on the EventReceivers
collection. Once the new receiver has been created, you need to give it the fully qualified assembly name that points to the code you have written and deployed as well as provide a sequence number and indicate the type of event to which the receiver responds.
The problem with deploying event receivers by manually writing code that installs the receiver against a specific instance of a list is that you don’t get much reuse benefit from that receiver.
When developing SharePoint Solutions that include code that responds to list events, those event receivers are often part of a Feature definition. When including an event receiver in a Feature definition, you can indicate the type of list for which your code will be listening for events by specifying the list’s template ID in the Feature definition itself.
Listings 7.3 and 7.4 show the Feature.xml
and Elements.xml
files that configure a Feature that contains a list item event receiver.
Listing 7.3. Feature.xml
Listing 7.4. Elements.xml
After you have the Feature.xml
and Elements.xml
files, you can deploy them into your SharePoint TemplateFeatures
directory. After they are in the directory, use the following stsadm.exe
command to install the Feature:
Stsadm -o installfeature -filename FeatureDirectoryFeature.xml
Use the following stsadm.exe
command to activate the Feature on your website (make sure you change the relative directory paths and URLs to match your configuration):
Stsadm -o activatefeature -filename FeatureDirectoryFeature.xml -url "http://server/web site"
After you install and activate the Feature, you must run iisreset
for SharePoint to start making use of the newly registered event receivers.
When the Feature is installed and activated, you can verify this using the Site Features page, as shown in Figure 7.1.
Figure 7.1. Site Features list after installing event handler feature.
You might have noticed that in the Elements.xml
file you had to specify the list template ID as a raw number. Table 7.5 provides a list of template IDs and the built-in SharePoint list types to which they correspond.
Unfortunately, you cannot listen for multiple list template IDs within the same Feature. If the Solution you are delivering involves listening for events on multiple list template IDs, you should create a Solution with multiple Features, where each Feature contains event receivers for a single list template ID.
Deploying event receivers with content types follows the same pattern as deployment with Features. First, you must create the strongly named, signed Assembly and place it in the GAC of the destination server. If you are deploying to a farm, the event receiver Assembly must be in the GAC of every front-end server. After the Assembly has been deployed, it is just a matter of creating a content type with a Feature and using the procedure for Feature-based event receiver deployment discussed in the preceding section.
One of the most powerful new abilities given to SharePoint developers with the new version of SharePoint is the ability to write code that responds to events on any list, not just document libraries. This chapter provided an illustration of how to write list event receivers, list item event receivers, and how to deploy those event receivers. You can even use the information in this chapter to create event receivers for events that take place at the site scope.
Responding to list events and deploying that code programmatically or via Solutions, Features, and content types give you tremendous power and flexibility when building your SharePoint-based solutions.