Wednesday, December 14, 2011

Avoiding System Account in “Modified By”

When creating event receivers or workflows you frequently need to update the list item in question in that code. The problem with doing this is it typically requires changing the user context to someone who has permissions to perform the operation (frequently the System Account or another privileged user). You usually want these changes to occur behind the scenes and not be displayed to the user.

Consider the following little example for an event receiver:

public override void ItemAdded

                          (SPItemEventProperties properties)

{

   SPUser adminUser =

       properties.Web.EnsureUser("GEEKTRAINER\\charrison");

   using (SPSite site =

       new SPSite(properties.WebUrl, adminUser.UserToken))

   using (SPWeb web = site.OpenWeb()) {

     SPList list = web.Lists[properties.ListId];

     SPListItem item = list.GetItemById(properties.ListItemId);

 

     item.BreakRoleInheritance(true);

     item.Update();

   }

}

Pretty simple demo code for an event receiver. First I’m changing context[1] to a privileged account. Then I’m loading up new instances of the SPSite, SPWeb, SPList and SPListItem objects in order to make changes. I then perform the change and call Update() on the list item. The result? Well, the result looks like this for a user named Susan who creates a new announcement in this list:

BeforeCallingSystemUpdate

You’ll notice that it says the item was updated by Christopher, which is true – it was modified by Christopher, but that’s not the display I’m looking for. The item was created by Susan, and Susan should be the only person shown on the Modified By column.

Thus enter SystemUpdate[2]. SystemUpdate allows you to change a list item without changing either the Modified or Modified By fields. Behind the scenes, SystemUpdate will still update the audit log, however it will not send alerts for the changes.

SystemUpdate has two two overloads, SystemUpdate() and SystemUpdate(boolean). The second overload allows you to control if a new version is created by passing in true. The default (no parameters overload) is false – don’t create a new version.

If we update the line:

item.Update();

to be:

item.SystemUpdate();

and then create a brand new item again as Susan, you’ll notice the difference (the one titled “Modified by Current User”:

AfterCallingSystemUpdate

SystemUpdate allows you to make changes to list items in code and essentially “hide” those changes from the user. The audit logs will still record the change, but the user will not see the dreaded “System Account” (or other account) in the Modified By column.

[1] See blackninja for a demo on changing context.
[2] See MSDN for the full documentation.

No comments:

Post a Comment