Situation
I have written a small Event Handler to automatically copy the file name and version to custom text fields in order to be able to use them in Microsoft Word.
- ItemAdded
- ItemCheckedOut
- ItemUpdated
Here's a small sample of the code I'm using:
public override void ItemUpdated(SPItemEventProperties properties)
{
SPListItem item = properties.ListItem;
CopyMetadata(ref item, "ItemVersion", item.Versions[0].VersionLabel);
...
item.SystemUpdate(false);
}
Problem
This code runs flawless as long as I don't change the file name. Changing the file name throws the following exception:
There is no file with URL 'Workinstructions/Test.doc' in this Web.
StackTrace:
at Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish)
at Microsoft.SharePoint.SPListItem.AddOrUpdateItem(Boolean bAdd, Boolean bSystem, Boolean bPreserveItemVersion, Boolean bNoVersion, Boolean bMigration, Boolean bPublish, Boolean bCheckOut, Boolean bCheckin, Guid newGuidOnAdd, Int32& ulID, Object& objAttachmentNames, Object& objAttachmentContents, Boolean suppressAfterEvents)
at Microsoft.SharePoint.SPListItem.UpdateInternal(Boolean bSystem, Boolean bPreserveItemVersion, Guid newGuidOnAdd, Boolean bMigration, Boolean bPublish, Boolean bNoVersion, Boolean bCheckOut, Boolean bCheckin, Boolean suppressAfterEvents)
at Microsoft.SharePoint.SPListItem.SystemUpdate(Boolean incrementListItemVersion)
Cause
When using the SPListItem instance from properties.ListItem it seems that this instance is invalid at some times. Trying to work with this instance throws the exception.
I have only been able to reproduce this issue when Variations (MOSS Publishing Feature) are enabled on the Site Collection.
Solution
You will probably be frowning when looking upon this code but it does bypass the above issue. Basically I'm pausing the thread until I can get the item after the rename by checking the AfterUrl. To avoid an endless loop I limit the number of tries to 100.
///
/// Get the ListItem by opening a new SPWeb and using SPList.GetItemById.
/// Wait for the rename to have finished before returning the item.
///
///
/// Item
///
/// This issue occurs mostly when the following conditions are met:
/// - Variations are enabled and the SPList resides in a SPWeb in the Variation Hierarchy
/// - The item is renamed
/// - SPListItem.SystemUpdate(), SPListItem.UpdateOverwriteVersion() is called in the ItemUpdated Event Handler
///
private SPListItem GetRenamedListItem(ref SPItemEventProperties properties)
{
SPListItem result = null;
for (int i = 0; i < 100; i++)
{
result = properties.OpenWeb().Lists[properties.ListId].GetItemById(properties.ListItemId);
if (result.Url.Equals(properties.AfterUrl))
break;
Thread.Sleep(100);
}
return result;
}
In every event method I'm overriding I just use this method to retrieve the item reference.
Applies To
MOSS 2007 (I have only experienced this issue when Variations were enabled on the Site Collection)