In SharePoint platform, we know, when we update an item or a folder, we should run the updating code with with elevating privileges, and set the item’s web’s “AllowUnSafeUpdate” property true. So we update an item will be like this:
SPSecurity.RunWithElevatedPrivileges(delegate(){
SPSite site = new SPSite(siteId);
SPWeb web = SPSite.OpenWeb(webId);
SPList list = web.Lists[listId];
SPListItem item = list.GetItemByID(itemId);
web.AllowUnSafeUpdate = true;
item.Update();
});
The code above will usually work ok, and this is our usual practice. But sometimes maybe we will get some COMEXception. I have experienced some unfortunately, following is the details of the exception:
Microsoft.SharePoint.SPException: Object reference not set to an instance of an object.—>System.Runtime.InteropServices.COMEXception(0x81020089):Object referencenot set to an instance of an object.
at Microsoft.SharePoint.Library.SPRequestInternalClass.UpdateFileOrFolderProperties(…..)
at Microsoft.SharePoint.Library.SPRequest.UpdateFileOrFolderProperties(……)
— End of inner exception stack trace —
at Microsoft.SharePoint.Library.SPRequest.UpdateFileOrFolderProperties
at Microsoft.SharePoint.SPFolder.Update()
my code:
list.ParentWeb.AllowUnsafeUpdates = true;
list.RootFolder.Properties[key] = value;
list.RootFolder.Update();
My code ran with elevated privileges, so what happened? I view the SPRequestInternalClass code with .net reflector, it doesn’t help. I just can know it maybe will give a COMEXception when you update a folder or item, but not the reason.
So what will cause this exception??I found?So many people experiencing the exception when I Googled it. ?The real reason is that?the updating item action caused other item event receive execute action. I don’t know when I have added a ListItemEventReceiver. We know the reason, but how can we prevent the item event receiver from executing? Sometimes we don’t want to cause the item event receiver executing when we update. Sometimes the list may have been registered some item event receivers we don’t know, and this occurs frequently when we do products, the customer may have added some event receivers for the list. We just want to update the item but not to causing the item event receiver executing, so we must prevent it.
How can we do it?
If you have developed any event receiver, you may remember that the event receiver have two override methods, one is?DisableEventFiring, and the other is?EnableEventFiring. The two methods are defined in?SPEventReceiverBase, and the?SPEventReceiverBase class have implemented them. We view the code with .net reflector, and we can find it calls an static method, all the event receiver share a static property. It means that wherever we invoke the two methods to enable or disable event firing, it will effect all the event receivers. So we can disable the event firing when we update an item, because the two methods are protected, so we can invoke the methods through reflection, the code like this:
public static void RunWithEventFiringDisabled(Action action)
{
Type typeInfo = typeof(SPEventReceiverBase);
MethodInfo disable = typeInfo.GetMethod(“DisableEventFiring”, BindingFlags.Instance | BindingFlags.NonPublic);
MethodInfo enable = typeInfo.GetMethod(“EnableEventFiring”, BindingFlags.Instance | BindingFlags.NonPublic);
SPEventReceiverBase receiver = new SPEventReceiverBase();
try
{
disable.Invoke(receiver, null);
action();
}
finally
{
enable.Invoke(receiver, null);
}
}
When we want to update an item or folder without causing item event receiver executing, we can call this method like this RunWithEventFiringDisabled(delegate(){//our update code;}). This method and?RunWithElevatedPrivileges used together when you update an item will resolve normal update error issue.