Among the two approaches which one is preferred with run with elevated privileges?
First Approach:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite curSite = new SPSite(SPContext.Current.Site.ID))
{
using (SPWeb web = curSite.OpenWeb(SPContext.Current.Web.ID))
{
try
{
web.AllowUnsafeUpdates = true;
\\ do your stuff
}
catch (Exception e)
{
}
finally
{
web.AllowUnsafeUpdates = false;
web.Dispose();
}
}
}
});
Second Approach:
SPSite oSite = SPContext.Current.Site;
SPWeb oWeb = SPContext.Current.Web;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite curSite = new SPSite(oSite.ID))
{
using (SPWeb web = curSite.OpenWeb(oWeb.ID))
{
try
{
web.AllowUnsafeUpdates = true;
\\ do your stuff
}
catch (Exception e)
{
}
finally
{
web.AllowUnsafeUpdates = false;
web.Dispose();
oWeb.Dispose();
oSite.Dispose();
}
}
}
});
Are any of them suspected to throw “The web being updated was changed by an external process” exception ?
First of all, you should make a call to
SPWeb.ValidateFormDigest()orSPUtility.ValidateFormDigest()before elevating the code. This will get rid of unsafe update not allowed with GET request, and avoid you to setup the AllowUnsafeUpdate property.Secondly, as Nigel Whatling mentioned, you are disposing context object in your second code. You don’t have to dispose them. To be simple, only dispose object you are instantiating yourself. A code like yours can cause side effects, as other SharePoint component may require access to SPContext.Current.XX objects. This is probably the root of your issue.
Thirdly, as you are using the using construct, you don’t have to call .Dispose() on the variable you set up in the using header. Actually, the role (and actually benefit) of the using construct is that you don’t have to care to dispose the object. As soon as the block code exits, even if there was an exception, the .Dispose() method is called on your object.
To conclude, your code should be changed to that :
A side note: to elevate a code, you have two options. The one you use here (call to
SPSecurity.RunWithElevatedPrivileges) or instantiating a new SPSite with the SystemAccount token :This will allow you to run elevated code outside a webapplication.
You should also consider using some utility code to wrap such operations in a more functional way. I’m used to use code like this :
Using such code, you can simply do, somewhere in your code :