Wednesday 5 October 2011

Updating properties when you save a file from an external program and properties.ListItem.SystemUpdate();

The other day I came across, by accident, with one of my worst nightmares, update the properties of a file when the file is uploaded by an external program (Non Office 2010), in fact it was Adobe Acrobat Reader.

After spending a couple of hours trying to figure out how Adobe Reader works with Sharepoint 2010, I found out that before saving the file it does a checkin so it can add all the properties.

My first approach was to develop an Event Receiver and go ItemAdded(…) so I could add the properties without any problem. When I tried that the item was updated BUT Adobe Reader throw an error saying that the file didn’t exist. Quite weird. So I assumed that Adobe decided to do that because it lost control of the file, at the end of the day I was modifiying the properties with my lovely Event Receiver.

To avoid that error I decided to go to the ItemCheckedIn(…) event and modify my properties, so Adobe should be happy. I used the elegant method properties.ListItem.SystemUpdate() to update the properties, otherwise I was going to receive a similar error, well, it is the first time I use this method, but it worked really well.

properties.ListItem.SystemUpdate(): Updates the database with changes that are made to the list item without changing the Modified or Modified By fields.

Some important notes on using Update vs SystemUpdate.
For Update:  Once you update, the modified by and modified dates change to when the code execute and may show the item as being last modified by "System Account".  The code also works with the item like it has nothing at all to do with the previous version.  User updates, then Code updates.

For SystemUpdate(Optional Boolean value)
If you are stuck trying to update a field for a document library, please be aware of two things in Sharepoint 2007/WSS 3.0.
1. Even if you are NOT using Checked out/checked in, the document still has a SPCheckOutStatus.ShortTerm attached to it for a brief period of time.  Trying to SPListItem.Update or SPFile.Item.Update at this point will likely tell you that the file is locked for editing.  There is a .checkoutexpires property to check if you absolutely must wait for the item to be checked back in.  (e.g. Are they really done with that darn thing?)
2. Even if you do NOT have versioning turned on, you are, in fact, working with a new version of the document.  Use SPListItem.SystemUpdate(false) in order to bypass a short term locked document.

Full Example:
file.Item["Status"] = "Pending";
file.Item.Web.AllowUnsafeUpdates = true;
file.Item.Update() //fails miserably on ItemChanged due to the SPCheckOutStatus.ShortTerm lock.
file.Item.SystemUpdate(false); //This works while the user still has the document open. 
file.Item.Web.AllowUnsafeUpdates = false;

I attach the code just ion case you want to deliver solutions conected to external programs. Remember that this code comes from an Event Receiver:

/// <summary>
/// An item was checked in
/// </summary>
public override void ItemCheckedIn(SPItemEventProperties properties)
{
   try
   {              
      //## Propperty to be updated
      properties.ListItem["client"] = "222222";
      //## Updating with systemUpdate()
      properties.ListItem.SystemUpdate();        
   }
   catch (Exception ex)
   {
      Microsoft.SharePoint.Administration.SPDiagnosticsService diagSvc = Microsoft.SharePoint.Administration.SPDiagnosticsService.Local;
      diagSvc.WriteTrace(0, new SPDiagnosticsCategory("PDFFileUpdater", TraceSeverity.Monitorable, EventSeverity.Error), TraceSeverity.Monitorable, "Writing to the ULS log:  {0}", new object[] { ex.ToString() });
   }
   base.ItemCheckedIn(properties);
}

No comments: