Monday, February 05, 2007

MOSS ItemAdded event - problem

Conclusion: The reason for this behavior is due to the fact that within my custom event handler I invoke a web service - bad idea. This unexpectedly changes the user profile of Internet Information Server - resulting in the error described. For now - don't invoke web services from within event handlers :-(

I'm testing the DocIntegrityPolicy example found in ECM toolkit. It provides an example of implementing a custom information management policy. When new items are added to a document library, the ItemAdded event set the value of a certain property to a MH5 hash value of the file in order to ensure integrity of the file. So far so good.

Unfortunately, this behavior introduces a problem in SharePoint. Modifying the content during the upload process results in an error: "The file has been modified by on ". This message is somehow understandable - as the item truely has been modified. But it raises the issue how to add fields such as barcodes and labels to a document in a library.

Please also refer to this blog for a similar example.

The sequence of events is outlined below:







1. Pick the document for upload


2. Enter document properties

3. Error reported


The good news is the the document is uploaded just fine - with all properties (including the ones added in ItemAdded) set as expected. But why the error?


To make things even more compliacated it turns out that the modification of the list itself during event registration (i.e. adding the new field to the list) raises another issue with the error: "The object has been updated by another user since it was last fetched".


10 comments:

Anonymous said...

Hi, I'm struggling with the same error. The error seems to appears if your item.Update() is executed after the upload mask is loaded by SharePoint. Also item.SystemUpdate() didn't help for me.
If I refresh the upload mask after some seconds before I proceed I don't get the error. Please let me know you have any news.

Morten Marquard said...

Did you read my conclusion? The reason for the issue I had was the fact that IIS changes the security context when invoking a web service. Look into what type of things are are doing ***before** you invoke Item.Update()

Ryan Thomas said...

I'm having a similar problem. The code sample is pasted below. Basically, if I try to modify the value of a column in the ListItem and call .Update() while in the context of ItemAdded I get file has been modified error. If I comment out the Update it works every time (but obviously that doesn't help me). I'm not doing anything special to this List. Thanks!
-Ryan

public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
try
{
if (properties.ListTitle == "File Exchange")
{
SPSite mainSite = new SPSite(ConfigurationSettings.AppSettings["QuantSiteRoot"]);
SPWeb site = mainSite.OpenWeb();

try
{
Guid newListGuid = site.Lists.Add(properties.ListItem.DisplayName, properties.ListItem.DisplayName + " Discussion", site.ListTemplates["Discussion Board"]);
}
catch (Exception ex)
{
// List already there??
}

SPList newForum = site.Lists[properties.ListItem.DisplayName];

SPGroup groupMember = site.SiteGroups[ConfigurationSettings.AppSettings["QuantMemberRole"]];
SPRoleDefinition rolDef = site.RoleDefinitions.GetByType(SPRoleType.Contributor);
SPRoleAssignment roleAssign = new SPRoleAssignment((SPPrincipal)groupMember);
roleAssign.RoleDefinitionBindings.Add(rolDef);

if (!newForum.HasUniqueRoleAssignments)
{
newForum.BreakRoleInheritance(true);
}
newForum.RoleAssignments.Add(roleAssign);


SPListItem item = properties.ListItem;
item["Discuss"] = newForum.DefaultViewUrl + ", Discuss";
item.Update();
}
}
catch (Exception e)
{
}
}

Morten Marquard said...

Hi Ryan,
I would look into potential security issues of your code. First of all - the event handler runs in the context of which user? Does this user have proper rights to create new lists and add items to the list?

Further - I would invoke :
this.DisableEventFiring();
Item.SystemUpdate(false);
this.EnableEventFiring();

rather than
Item.Update();

Good look - and please let me know if it works or not.

Anonymous said...

I tried all the stuff you mentioned. But no luck. I am getting that error that the file has been modified. I have been trying for more than a month to figure this out. I can only see putting a 2 minute delay in the ItemAdded works if the user click ok with in 2 minutes of upload. But delay increases number of sleeping threads and kills the prod environment. Is there a solution for this error at all other than putting a delay?

Unknown said...

If anyone is still having problems with that I can confirm that this worked for me:

DisableEventFiring();
Item.SystemUpdate(false);
EnableEventFiring();

thanks Morten

Morten Marquard said...

I think there is much more to it than just the code you suggested. But in principle the stuff should work.

But - often ItemAdded is invoked without an item. This can happen in several situations, e.g. Copy-paste operation. In such a situation the code doesn't work - as no item is passed. An even if you find a way to retrieve the new item (we came up with various ideas to retrieve the item not passed to ItemAdded) it often causes issues in this situation. And the security contest of IIS still seems to be an issue.

Anonymous said...

Incredible!

this.DisableEventFiring();
item.SystemUpdate(false);
this.EnableEventFiring();

Work for me!

David Matons.

Preetam Patil said...

whenever i copy a document from one libraray to anotherI get Copysource property blank

Preetam Patil said...

Whenever i copy document to another library i get copysource property blank