This topic has not yet been rated - Rate this topic

SPItemEventReceiver.ItemUpdating Method

Handles the synchronous event that occurs before an item is changed.

Namespace:  Microsoft.SharePoint
Assembly:  Microsoft.SharePoint (in Microsoft.SharePoint.dll)
Available in Sandboxed Solutions: Yes
Available in SharePoint Online
public virtual void ItemUpdating(
	SPItemEventProperties properties
)

Parameters

properties
Type: Microsoft.SharePoint.SPItemEventProperties
The properties of the event handler.
Exception Condition
ArgumentNullException

properties is null.

This event can be used in response, for example, to a form edit, a datasheet post, an object model call, or a Web service call.

When you add a new item, only the ItemAdding event is raised. However, in cases where Explorer View is used, both the ItemAdding and this events are raised. In such cases, this event always occurs after the ItemAdding event occurs.

When a Boolean column value in a list is set to true and the ItemUpdating method is called, the AfterProperties property reports -1 as the value instead.

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
Dealing with AfterProperties in ItemUpdating()
There are some things to keep in mind when reading out the changed values of a list item the proper way.
  • During ItemUpdating, the BeforeProperties are empty, so you cannot use them to get the old values of the item. Instead, use properties.ListItem[<field name>] to access the field values.
  • The new values can be found in the AfterProperties. However, the AfterProperties sometimes do not hold the object types you would expect (often it turns out to be a string). In these cases, the best way to create a field value is to use this pattern:

        <FieldValueType>
     myFieldValue = new <FieldValueType>(properties.AfterProperties[<field name>].ToString());

        rather than the "natural" way:

        <FieldValueType>
     myFieldValue = properties.AfterProperties[<field name>] as <FieldValueType>;
  • The AfterProperties.ChangedProperties do not contain what you might expect. In fact, they are empty. If you want to know what has changed, it's up to you to compare the list item with the AfterProperties.
  • For multi-lookup user fields, the value type is SPFieldUserValueCollection. For single-lookup fields, it is SPFieldUserValue. For non-user lookup fields, there are SPFieldLookupValueCollection and SPFieldLookupValue, respectively, which are the base classes for the user field value types. You need to instantiate them this way:

        SPWeb myWeb = properties.OpenWeb();
        SPFieldUserValueCollection myCol = new SPFieldUserValueCollection(myWeb, properties.AfterProperties[<field name>].ToString());

In detail, there are some things to be aware of when using multi-lookup user fields in an ItemUpdating() event receiver:
  • The SPFieldUserValueCollection you get from the list item (old user set) has the LookupValue property of its SPFieldUserValue instances set to the full name of the user. Note that this is not equal to the LoginName property of the SPUser object!
  • The SPFieldUserValueCollection you get from the AfterProperties (new user set) has the LookupValue property of its SPFieldUserValue instances set to the login name of the user, rather than the full name.
  • All LookupId properties of SPFieldUserValue instances taken from the AfterProperties are set to -1 if the according users were not a member of the old user set (list item) as well! If they are however, the correct LookupId is returned.

        If you want to get the proper ID of a user which was added during the update of the list item, you can query the AllUsers property of the SPWeb object:

        SPWeb myWeb = properties.OpenWeb();
        SPFieldUserValueCollection newUsers = new SPFieldUserValueCollection(myWeb, properties.AfterProperties[<field name>].ToString());
        SPFieldUserValue firstUser = newUsers[0];
        int myUserId = myWeb.AllUsers[firstUser.LookupValue].ID;

        Note that this will not work with a SPFieldUserValue derived from the list item, as the lookup value contains the full name then, and the indexer of AllUsers expects the LoginName or an ID. However, there is no problem, since in this case the LookupId is correct.
Taking all of this into account, the following code will get you the users who were dropped (given that "oldUsers" is a SPFieldUserValueCollection taken from the list item and "newUsers" is a SPFieldUserValueCollection taken from the AfterProperties):

foreach (SPFieldUserValue oldUser in oldUsers)
{
     if (newUsers.Find(x => x.LookupId == oldUser.LookupId) == null)
     {
          // oldUser is not contained in newUsers
     }
}

And the following will get you the users who were added:

foreach (SPFieldUserValue newUser in newUsers)
{
     if (oldUsers.Find(x => x.User.LoginName == newUser.LookupValue) == null)
     {
          // newUser is not contained in oldUsers
      }
}