Wednesday, July 11, 2007

RunWithElevatedPrivileges, watch out for the site context

Soon or later most SharePoint developers use RunWithElevatedPrivileges. We do that either to grant temporary access to files and folders not accessible by the current user or to execute some other action, which requires higher privileges. One thing I constantly forget about that always gets me with an "Access denied" error is when I omit the fact that the SPSite/SPWeb objects are initialized differently for different user contexts. Have a look at this code:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPWeb web = SPContext.Current.Web;

// do something that's not allowed for the current user, but it is ok for the elevated user

SPFile file = web.GetFile(restritedFileUrl);

string readProperty = file.Properties["Name"].ToString();
});

Seems like done deal. Not so.... The problem is that the SPWeb object from the current context is initialized using the current user's credentials, so even though we run the code snippet with elevated privileges the actual access to the file is still restricted. To circumvent this we have to create a new SPSite/SPWeb object within the elevated code, where we run in the context of the elevated user. Then we can perform the restricted action. Since the SPSite/SPWeb objects are created explicitly we have to also dispose of them (more about why we need to do this here). The modified working code becomes:

string siteUrl = SPContext.Current.Web.Url;

SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPSite sysSite = new SPSite(siteUrl);
SPWeb sysWeb = sysSite.OpenWeb();

// do something that's not allowed for the current user, but it is OK for the elevated user

SPFile file = sysWeb.GetFile(restritedFileUrl);

string readProperty = file.Properties["Name"].ToString();

sysWeb.Dispose();

sysSite.Dispose();

});

Access granted...

Dovizhdane!