Adding a Project to a Category

Brian Smith from PSS has passed along this sample that we thought might be helpful:

The scenario here is that you have a lookup table that shows the categories you want users to select from when creating a project, and then the GUID for the "real" security category is held in the description for the lookup table value.  You make the CF that feeds from the Lookup Table a required Project Level text field.  The Project.Created event fires and the dataset is read - the custom field identified and the GUID of the security category is then used to add the project to the security category.

No error checking or exception handling is shown - you can do this bit. You would also need to set the categories to the rule "only projects...".  I've hardcoded my lookup table and a reference required to the Microsoft.Office.Project.Server.Library and Events. A Web References to LookupTable, Project, Security and LoginWindows is also required.

The code will run as the user running the services - so you will either need that account to have PWA permissions or to change to use impersonation.

using System;
using System.Collections.Generic;
using System.Net;
using System.Diagnostics;
using System.Text;
using Microsoft.Office.Project.Server.Events;
using Microsoft.Office.Project.Server.Library;

namespace TestEventHandler
{

    public class AutoCategory:ProjectEventReceiver
    {

        public override void OnCreated(PSContextInfo contextInfo, ProjectPostEventArgs e)
        {

            // cfGuid holds CF for Project Category
            Guid cfGuid = new Guid("9bbc698f-5c1d-4f8d-a3d0-163006416bf2");

            // ltGuid holds LT for Categories
            Guid ltGuid = new Guid("625bab60-4427-4f0b-941b-9860d1293338");

            // lt_Struct_Uid gets the id for the selected LT value
            Guid lt_Struct_Uid = new Guid("00000000-0000-0000-0000-000000000000");

            // securityCategoryGuid gets the Security Categorty Guid from the Descriptio field in the lookup table
            Guid securityCategoryGuid = new Guid("00000000-0000-0000-0000-000000000000");

            // 32 is used to just get the CF entities from the readProjectEntities
            const int PROJECT_ENTITY_TYPE_PROJECTCUSTOMFIELD = 32;

            Guid SECURITY_CATEGORY_OBJECT_TYPE_PROJECT = new Guid("1771B1C0-6E26-4FB3-A480-C798AB506E82");

            WebSvcLoginWindows.LoginWindows loginWindows = new TestEventHandler.WebSvcLoginWindows.LoginWindows();
            WebSvcProject.Project project = new TestEventHandler.WebSvcProject.Project();
            WebSvcSecurity.Security security = new TestEventHandler.WebSvcSecurity.Security();
            WebSvcLookupTable.LookupTable lookupTable = new TestEventHandler.WebSvcLookupTable.LookupTable();

 

            //login to Project Server - this assumes the event service has a login with permissions

            // Impersonation would be better
            loginWindows.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/LoginWindows.asmx";
            loginWindows.Credentials = CredentialCache.DefaultCredentials;
            loginWindows.Login();

            // Get the dataset
            project.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/Project.asmx";
            project.Credentials = CredentialCache.DefaultCredentials;

            lookupTable.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/LookupTable.asmx";
            lookupTable.Credentials = CredentialCache.DefaultCredentials;

            security.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/security.asmx";
            security.Credentials = CredentialCache.DefaultCredentials;

            WebSvcProject.ProjectDataSet dsProjectDataSet = new TestEventHandler.WebSvcProject.ProjectDataSet();

            dsProjectDataSet = project.ReadProjectEntities(e.ProjectGuid, PROJECT_ENTITY_TYPE_PROJECTCUSTOMFIELD, TestEventHandler.WebSvcProject.DataStoreEnum.WorkingStore);

            for (int i = 0; i < dsProjectDataSet.ProjectCustomFields.Count; i++)
            {
                if (dsProjectDataSet.ProjectCustomFields[i].MD_PROP_UID == cfGuid)
                {
                    lt_Struct_Uid = dsProjectDataSet.ProjectCustomFields[i].CODE_VALUE;
                }
            }

            Guid[] arrayLtUid = new Guid[1]{ltGuid};
            WebSvcLookupTable.LookupTableDataSet dsLookupTable = new TestEventHandler.WebSvcLookupTable.LookupTableDataSet();
            dsLookupTable = lookupTable.ReadLookupTablesByUids(arrayLtUid, false, 1033);

            for (int i = 0; i < dsLookupTable.LookupTableTrees.Count; i++)
            {
                if (dsLookupTable.LookupTableTrees[i].LT_STRUCT_UID == lt_Struct_Uid)
                {
                    securityCategoryGuid = new Guid(dsLookupTable.LookupTableTrees[i].LT_VALUE_DESC.ToString());
                }
            }           

WebSvcSecurity.SecurityCategoriesDataSet dsSecurityCategories
   = new TestEventHandler.WebSvcSecurity.SecurityCategoriesDataSet();

// Read the existing values for the security category into the dataset
dsSecurityCategories = security.ReadCategory(securityCategoryGuid);

            // Get a new objects row to put the created project into

            WebSvcSecurity.SecurityCategoriesDataSet.SecurityCategoryObjectsRow dsSecurityCategoryObjectsRow
= dsSecurityCategories.SecurityCategoryObjects.NewSecurityCategoryObjectsRow();

            //Set the values
            dsSecurityCategoryObjectsRow.WSEC_OBJ_TYPE_UID = SECURITY_CATEGORY_OBJECT_TYPE_PROJECT;
            dsSecurityCategoryObjectsRow.WSEC_CAT_UID = securityCategoryGuid;
            dsSecurityCategoryObjectsRow.WSEC_OBJ_UID = e.ProjectGuid;

            // Add the row to the dataset and then pass to SetCategories to update
            dsSecurityCategories.SecurityCategoryObjects.AddSecurityCategoryObjectsRow(dsSecurityCategoryObjectsRow);

            // Create an EventLog instance and assign its source.
            EventLog myLog = new EventLog();
            myLog.Source = "Project Event Handler";

            // Get information from the event arguments, and

            // write an entry to the Application event log.
            string userName = contextInfo.UserName.ToString();
            string projectName = e.ProjectName.ToString();
            string secCatUid = securityCategoryGuid.ToString();
            int eventId = 3652;
            string logEntry;

 

            logEntry = "User: " + userName +

                    "\nProject: " + projectName +

                    "\nSecurity Category Uid: " + secCatUid;

                myLog.WriteEntry(logEntry, EventLogEntryType.Information, eventId);

            security.SetCategories(dsSecurityCategories);           

        }
    }
}