Here is a very complete article written by Damon Armstrong on ItemUpdating and ItemUpdated event receivers firing twice on SharePoint 2010, and how to work around this issue.
If you need to set up a testing environment for retention policies in SharePoint 2010 and you decide to create a retention stage that looks like the following:
Declared Record + 1 Day Move to Recycle Bin
You will notice that the retention policy does not run as expected. This is normal behavior because there are two timer jobs that need to run sequentially to achieve the desired result and by default both these timer jobs are set to run on a weekly schedule. These are the timer jobs that need to be run:
- Information management policy
- Expiration policy
To allow for your short-term retention policies to work properly, you need to change their schedule to run daily:
- Go to Central Admin
- Monitoring
- Review job definitions
- Look for “Information management policy” and click it
- Change the radio button in the Recurring Schedule to Daily and set the time to run at midnight:
- Click OK
- Look for “Expiration policy” and click it
- Change the radio button in the Recurring Schedule to Daily and set the time to run at 2 AM:
You can also use the Run Now button in both these timer jobs to test documents that should already have been disposed of.
Programmatically declaring and undeclaring records can be useful in case you need to modify dates or metadata to trigger retention.
An example of this would be: Multiple court case documents sitting declared as records in a record library, with document disposition rules that trigger disposition 3 years after the case resolution date.
There is no way you could have put in the case resolution date prior to the completion of litigation and the documents need to be in the record center to prevent tampering with.
You could build an interface in a web part or _layouts page that allows a user to input the case resolution date and the code behind will
- undeclare all the records about this case
- add the resolution date
- redeclare the record.
At this point disposition rules would kick in and dispose of the document after the required time period.
The code used to declare and undeclare the records is as follows:
You need to add the following namespace:
using Microsoft.Office.RecordsManagement.RecordsRepository;
Then you need the following bits of code to run against all the documents that match the selected court case:
SPSecurity.RunWithElevatedPrivileges(delegate() { using (site = new SPSite(siteurl)) { using (spWeb = site.OpenWeb(webguid)) { list = spWeb.Lists[listguid]; if (list != null) { item = list.Items[itemguid]; //Checking whether the item is a record or not if (item != null && Records.IsRecord(item)) { Records.UndeclareItemAsRecord(item); //undeclares the item as a record //UPDATE ITEM HERE Records.DeclareItemAsRecord(item); //declares the item as a record } } } } });
Update:
I just found an MSDN article that identifies anotehr option to updating records programatically. It makes use of the Records.BypassLocks method which is called using the following block of code:
using Microsoft.Office.RecordsManagement.RecordsRepository; SPSecurity.RunWithElevatedPrivileges(delegate() { Records.BypassLocks(myListItem, delegate(SPListItem item) { //Perform any action on the item. }); });
Hope this code will be helpful to you. Let me know in the comments or via Twitter.
There is more to come soon. Stay tuned!