1
votes

I have a custom list definition with an event receiver that overrides ItemUpdating. The list has content approval turned on, along with create major and minor versions.

If the item is being approved, I want to set a boolean field (Is Published?) without affecting the version and approval status. I understand SystemUpdate(false) is suppose to do this, however it does not persist the bool value. If I use Update() or SystemUpdate(), the value is persisted but it doesn't set the approval status to Approved and throws the following error:

The file [filename] has been modified by [user] on [date].

public override void ItemUpdating(SPItemEventProperties properties)
{
    base.ItemUpdating(properties);
    EventFiringEnabled = false;
    try
    {
        if (IsChangingToApproved(properties))
        {    
            if (!Validate(properties))
            {// This person can't approve
                properties.ErrorMessage = "You don't have appropriate permissions.";
                properties.Status = SPEventReceiverStatus.CancelWithError;
                properties.Cancel = true;
            }
            else
            {// Set the IsPublished flag to true                        
                var isPublishedField = properties.List.Fields["Is Published?"];
                if (isPublishedField != null)
                {
                    properties.ListItem[isPublishedField.InternalName] = true;

                    // Doesn't update bool, ItemUpdating event functions normally
                    properties.ListItem.SystemUpdate(false); 

                    // Updates bool, but ItemUpdating event does not complete
                    //properties.ListItem.Update(); 
                    //properties.ListItem.SystemUpdate();

                }
            }
        }
    }
    catch (Exception ex) { return; }
    finally { EventFiringEnabled = true; }
}

Things I've tried:

  • Updating the listItem with a using Site/using Web block instead of updating the item from the properties.
  • Setting the properties.AfterProperties["Is Published?"] field.
1

1 Answers

2
votes

You shouldn't call system update within your synchroneous event. Event without adding an additional version.

If you want to update the property prior to the update, you can change the afterProperties[""] and the change will be persisted if the update succeeded.

base.ItemUpdating(properties);
properties.AfterProperties["Is Published"] = true;

By the way you can also retrieve the publishing state using ListItem.ModerationInformation.Status == SPModerationStatusType.Approved (= is published and approved)

Relying on the ootb internal field will ensure that you won't have to mess with additional event receivers (watch out for the funny stuff like when the content deployment are running ...) and will ensure that the status will always be up-to-date.

Hope it helped.