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:
using Site/using Web
block instead of updating the item from the properties.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.