Adding a Project to a Category

Adding a Project to a Category

Rate This
  • Comments 3

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);           

        }
    }
}

 

Leave a Comment
  • Please add 8 and 7 and type the answer here:
  • Post
  • Hi!

    Thanx for an excellent article!

    I have a question that I was hoping you could answer. I'm wondering how to retrieve the different webservice-urls that you have hardcoded in you examplecode, from within the eventhandler?

    What I'd like to do is to "re-use" the logic that (I guess) allready is in use within the applicationlogic today.

    English is not my native language, so just to clearify what I mean;

    When for instance a project is saved, the client makes a call to the PSI by referencing the correct url. My question is simply, in what way does the client retrieve the url?

    Regards,

    YonZo

  • You may already have found an answer - but if not the blog at http://blogs.msdn.com/brismith/archive/2007/02/02/one-event-handler-and-multiple-pwa-sites-where-did-that-event-come-from.aspx should help

  • Brian/Chris,

    In the above sample, you show identifying the security objects of type PROJECT with a particular GUID (as shown in the following line):

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

    Q. Is this a hard-coded GUID in the product to identify the types?

    Q. If so, is there way to look this up dynamically?  

    Q. Where is the list of GUIDs for the different possible types of security objects?

    Q. Could this have been an enum that gets mapped internally in the PSI to the correct GUID?

    Thanks

Page 1 of 1 (3 items)