Using SPSite and SPWeb objects with RunWithElevatedPrivileges: Don’t cross the borders
This blog post is a contribution from David Wilborn, an engineer with the SharePoint Developer Support team.
Although it’s mentioned in the SPSecurity.RunWithElevatedPrivileges documentation, I find that there is still often a lack of clarity for developers when using SPSite and SPWeb objects in conjunction with RunWithElevatedPrivileges delegate.
The mistake I see the most often is attempting to get an SPSite or SPWeb object with elevated privileges by initializing the object inside of a RunWithElevatedPrivileges delegate, then using the object outside of the delegate:
SPSite elevatedSite = null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// BAD: This object will not correctly retain elevated status outside of the delegate!
badElevatedSite = new SPSite("https://mysharepointsite");
});
SPWeb web = badElevatedSite.RootWeb; // Will not have desired permissions
Another common issue is using an already initialized SPSite or SPWeb inside of a RunWithElevatedPrivileges delegate and assuming its permissions will be elevated:
SPSite site = new SPSite("https://mysharepointsite");
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// This SPWeb will NOT have elevated privileges, because "site" does not
SPWeb notElevatedWeb = site.RootWeb;
});
An SPSite and SPWeb object initialized inside of a RunWithElevatedPrivileges block will have indeterminate permissions when used outside of that block – in other words, sometimes the object will retain the elevated privileges and sometimes it will not. I’ve seen cases where a customer’s code written this way will work fine for months on end, then suddenly stop working when no code has changed!
So what’s the correct way to create SPSite and SPWeb objects with elevated privileges? Always create and dispose off the objects within the RunWithElevatedPrivileges delegate. Instead of elevating an existing object’s permissions, you’ll need to create a new object:
SPSite site = new SPSite("https://mysharepointsite");
// additional code using the site object
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Create a new elevated version of the same site collection object
using (SPSite elevatedSite = new SPSite(site.Id))
{
SPWeb elevatedWeb = elevatedSite.RootWeb;
// perform elevated operations with elevatedWeb here. . .
} // SPSite object gets disposed automatically
});
A simple rule of thumb is don’t “cross the border” with your SPSite and SPWeb objects – don’t use an object created outside of the RunWithElevatedPrivileges delegate within the delegate, and dispose all SPSite and SPWeb objects created within the delegate before the delegate completes.
Comments
- Anonymous
July 09, 2014
mmmmmmmmmmm - Anonymous
July 09, 2014
mmmmmmmmmmm - Anonymous
August 04, 2014
Thank You... - Anonymous
August 27, 2014
Thanks! One n00b step closer! - Anonymous
March 31, 2015
Problem in this codes - Anonymous
April 21, 2015
var success = true;
var currentWeb = SPHelper.GetCurrentWeb();
SPSecurity.RunWithElevatedPrivileges(() =>
{
using (var site = new SPSite(currentWeb.Site.ID))
{
using (var web = site.OpenWeb(currentWeb.ID))
{
var spList = GetList(web, Constants.Lists.SolutionList.Name);
web.AllowUnsafeUpdates = true;
if (spList != null)
{
spList.Items.DeleteItemById(Convert.ToInt32(id));
spList.Update();
web.AllowUnsafeUpdates = false;
}
else
{
success = false;
}
}
}
});