SharePoint – Run with Elevated Permissions vs Impersonate
Please use the page tabs to navigate through the article.
SPSecurity.RunWithElevatedPrivileges(delegate
{
using(SPWeb ElevatedWeb = ...)
{
//run elevated code here...
}
});
Which worked, but occasionally would come with security exceptions and other gremlins. My research found statements that it is better to impersonate than elevate, and for some time now I have been using adjusted code.
The main method runs the actual elevated code;
internal static void RunElevatedActions(Hashtable values)
{
RunElevatedActions(null, null, values);
}
internal static void RunElevatedActions(Guid SPSiteID, Guid SPWebID)
{
RunElevatedActions(SPSiteID, SPWebID, null);
}
internal static void RunElevatedActions(Guid SPSiteID, Guid SPWebID, Hashtable values)
{
if (SPSiteID == null)
{
SPSiteID = (Guid)values["SPSiteID"];
}
if (SPWebID == null)
{
SPWebID = (Guid)values["SPWebID"];
}
SPUserToken oSysToken = GetSysToken(SPSiteID);
using(SPSite oSite = new SPSite(SPSiteID, oSysToken))
{
Microsoft.SharePoint.Utilities.SPUtility.ValidateFormDigest();
using(SPWeb ElevatedWeb = oSite.OpenWeb(SPWebID))
{
//run elevated code here...
}
}
}
You notice I call it from either two means. The first is via a Hashtable contain all the values I need, including the Guids of the site and web, eg if I was working with an SPListItem;
Hashtable values = new Hashtable();
values.Add("SPSiteID", oItem.Web.Site.ID);
values.Add("SPWebID", oItem.Web.ID);
values.Add("SomeOtherSetting", SomeOtherValue);
RunElevatedActions(values);
or I can call it directly by feeding in the Guids;
RunElevatedActions(oItem.Web.Site.ID, oItem.Web.ID, null);
RunElevatedActions(ViewState["SPSiteID"], ViewState["SPWebID"], null);
The main method then sorts this out via;
if (SPSiteID == null)
{
SPSiteID = (Guid)values["SPSiteID"];
}
if (SPWebID == null)
{
SPWebID = (Guid)values["SPWebID"];
}
Personally I like the Hashtable most as it allows me to pass unlimited values and objects that I want to have actioned in the elevated code. This is particularly handy as it avoids referring back to a variable initiated by unelevated code which can cause issues.
The key difference about the remainder of the main method are the lines
SPUserToken oSysToken = GetSysToken(SPSiteID); ... using(SPSite oSite = new SPSite(SPSiteID, oSysToken))
These are the impersonate lines. First, the RunElevatedActions method gets the UserTokenof the System Account for the site;
private static SPUserToken GetSysToken(Guid SPSiteID)
{
SPUserToken sysToken = null;
using(SPSite oSite = new SPSite(SPSiteID))
{
SPUserToken sysToken = oSite.SystemAccount.UserToken;
}
if (sysToken == null)
{
SPSecurity.RunWithElevatedPrivileges(
delegate()
{
using(SPSite site = new SPSite(SPSiteID))
{
sysToken = site.SystemAccount.UserToken;
}
});
}
return sysToken;
}
then it connected it creates a connection to the site impersonating System Account using SPSite(SPSiteID, oSysToken).
Ive been running this new impersonate instead of elevate code for several months now and have found no problems whatsoever, in fact it has ran far smoother that the previous method.
Note: the line
Microsoft.SharePoint.Utilities.SPUtility.ValidateFormDigest();
is only required when running the method from Edit Mode – eg from EditForm.aspx.
For a full example of the code return to the top and select the “Full Example Code” tab…
internal static void UnElevatedCode()
{
Hashtable values = new Hashtable();
values.Add("SPSiteID", oItem.Web.Site.ID);
values.Add("SPWebID", oItem.Web.ID);
values.Add("SomeOtherSetting", SomeOtherValue);
RunElevatedActions(values);
}
internal static void RunElevatedActions(Hashtable values)
{
RunElevatedActions(null, null, values);
}
internal static void RunElevatedActions(Guid SPSiteID, Guid SPWebID)
{
RunElevatedActions(SPSiteID, SPWebID, null);
}
internal static void RunElevatedActions(Guid SPSiteID, Guid SPWebID, Hashtable values)
{
if (SPSiteID == null)
{
SPSiteID = (Guid)values["SPSiteID"];
}
if (SPWebID == null)
{
SPWebID = (Guid)values["SPWebID"];
}
SPUserToken oSysToken = GetSysToken(SPSiteID);
using(SPSite oSite = new SPSite(SPSiteID, oSysToken))
{
Microsoft.SharePoint.Utilities.SPUtility.ValidateFormDigest();
using(SPWeb ElevatedWeb = oSite.OpenWeb(SPWebID))
{
//
//run elevated code here...
//
}
}
}
private static SPUserToken GetSysToken(Guid SPSiteID)
{
SPUserToken sysToken = null;
using(SPSite oSite = new SPSite(SPSiteID))
{
SPUserToken sysToken = oSite.SystemAccount.UserToken;
}
if (sysToken == null)
{
SPSecurity.RunWithElevatedPrivileges(
delegate()
{
using(SPSite site = new SPSite(SPSiteID))
{
sysToken = site.SystemAccount.UserToken;
}
});
}
return sysToken;
}

Using a Console Application to perform SharePoint Tasks
[...] will be recorded as the the user you are logged on as, unless you perform a SystemUpdate() or Impersonate.Its very basic, but for one off runs or batches the information is effective; 6739 Items to be [...]
mnosiek
This line SPUserToken sysToken = new SPSite(SPSiteID).SystemAccount.UserToken; of the GetSysToken() method does not dispose SPSite, but it must.
aaron
Yes I think you are quite correct – thanks for spotting it and letting me know – I have adjusted the code to suit.