Challenge
However, when using SPSecurity.RunWithElevatedPrivileges to elevate rights we have a similar issue, but there's several lines of code that you'd like to be able to reuse between different methods. For example, you'll have to open a site (sometimes at least), open a web, and set AllowUnsafeUpdates on both site and web. And you still need to ensure that disposing works correctly.
If you create a method that, for example, simply returns an elevated web you'll have no control over whether that web is disposed or not in the end. And the code will become quite hard to manage later on as reusable blocks of code might have to manage both webs that shall be disposed and those that shouldn't be disposed (such as SPContext.Current.Web).
Solution
My solution? Write reusable methods that take a delegate for the actions to execute in elevated mode. I create overloads that cover all the needs for the project. But, let's look at an example.
A delegate
public delegate void WebCodeDelegate(SPWeb elevatedWeb);
The reusable code block
public static void ExecuteElevatedCode(Guid siteId, Guid webId, WebCodeDelegate webCode)Calling the reusable code
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Use "using" to automatically release site resources.
using (SPSite site = new SPSite(siteId))
{
site.AllowUnsafeUpdates = true;
// Open a web. Be sure to release resources!
SPWeb elevatedWeb = site.OpenWeb(webId);
try
{
elevatedWeb.AllowUnsafeUpdates = true;
// Execute delegate.
webCode(elevatedWeb);
}
finally
{
// Release web resources.
elevatedWeb.Dispose();
}
}
});
}
ExecuteElevatedCode(siteId, process.Id, delegate(SPWeb elevatedWeb)
{
SPList elevatedList = elevatedWeb.Lists[PROCESS_WEB_LIST_NAME];
SPListItem item = elevatedList.Items[0];
item[GUID_STATUS] = "status";
item[GUID_ERROR_DESCRIPTION] = "description";
item.Update();
});
Other examples of overloads
// Executes elevated code on the root web of the current site collection.
public static void ExecuteElevatedCode(WebCodeDelegate webCode)
// Executes elevated code on the root web of the specified site collection.
public static void ExecuteElevatedCode(SPSite site, WebCodeDelegate webCode)
// Executes elevated code on the specified web.
public static void ExecuteElevatedCode(SPWeb web, WebCodeDelegate webCode)
// Executes elevated code on the specified web (using the url as reference to the web).
public static void ExecuteElevatedCode(Guid siteId, string webUrl, WebCodeDelegate webCode)
// Executes elevated code on the specified list.
public static void ExecuteElevatedCode(SPList list, ListCodeDelegate listCode)
// Executes elevated code on the specified item.
public static void ExecuteElevatedCode(SPListItem item, ListItemCodeDelegate listItemCode)
So, that's it. Hope it'll be of help to someone!

0 comments:
Post a Comment