Project Server 2010 Delegation Audit Event Handler

On of the great new feature for Project Server 2010 is the ability to delegate Project Web App (PWA) to a colleague while you are out of the office, check the Project 2010 Ignite Administration slides and recordings for more information (Download Project 2010 Ignite Recordings and Slides). One of the many feedback I heard during the Ignite worldwide tour was to make it easier to track who became a delegate of who and when. Finally found some time to provide an example to address this request. I basically built a custom event handler that overrides these two UserDelegation events: OnActivated  and OnDeactivated (which are called when you click on either Start Delegate Session and Stop Delegate Session in PWA:

DelegationBy definition this information is stored in the ULS logs, so to make it easier to report, every time the above two events are fired I store in a custom table the delegate session information. After 2 hours of coding and testing voila! My very first Project Server 2010 custom event handler, so easy to do even a marketing guy can do it! Once the custom handler is running you can then leverage Excel and Excel Services to built a report that renders an audit of all Delegate activity in your PWA instance (as shown below). I just love the ease of extensibility of 2010…

Code download is location on MSDN Code Gallery: Project Server 2010 Delegation Audit Event Handler

Partial extract of C# code

// Track Delegation Activation
public override voidOnActivated(PSContextInfo contextInfo, UserDelegationActivatePostEventArgs e)
{
    // Standard processing
   base.OnActivated(contextInfo, e);

    // Build T-SQL command
   stringcmdText = string.Format("EXEC PS2010_InsertDelegationActivationChange '{0}','{1}',1", e.Delegation.DelegateUid.ToString(), e.Delegation.ResUid.ToString());

    // Store Resource field update
   ConnectAndExecuteNonQuery(connectionString, cmdText);
}

// Track Delegation Deactivation
public override voidOnDeactivated(PSContextInfo contextInfo, UserDelegationDeactivatePostEventArgs e)
{
    // Standard processing
   base.OnDeactivated(contextInfo, e);

    // Build T-SQL command
   stringcmdText = string.Format("EXEC PS2010_InsertDelegationActivationChange '{0}','{1}',0", e.Delegation.ResUid.ToString(), e.Delegation.DelegateUid.ToString());

    // Store Resource field update
   ConnectAndExecuteNonQuery(connectionString, cmdText);
}

Partial extract of T-SQL stored procedure used

     INSERT INTO dbo.PS2010_UserDelegationAudit (
        ACTIVATION_UID,
     DELEGATE_NAME,
      RES_NAME,
       DELEGATE_UID,
       RES_UID,
        START_DELEGATE,
     ACTIVATION_DATE
     ) 
  VALUES
  (NEWID(),
   @DelegateName,
  @ResourceName,
  @DelegateUID,
   @ResourceUID,
   @StartDelegate,
 GETDATE()
   )

Sample Report

image

Please find below a brief code sample if you want to create delegate programmatically (a clean way would be to create a PowerShell cmdlet to automate the C# logic creation):

 UserDelegationDataSet userDelegationDataSet;
UserDelegationDataSet.ResourceDelegationsRow row = userDelegationDataSet.ResourceDelegations.NewResourceDelegationsRow();
Guid delegationUID = Guid.NewGuid();
row.DELEGATE_UID = delegateUID; 
row.RES_UID = resUID; 
row.DELEGATION_FINISH = endDate;
row.DELEGATION_START = startDate;
row.DELEGATION_UID = delegationUID;
userDelegationDataSet.ResourceDelegations.AddResourceDelegationsRow(row);
resourceProxy.CreateDelegations(userDelegationDataSet);