Retrieve the Guid of a Custom Field Using its Name
posted May 7th, 2008 by Stephen SanderlinWithin the Project Object Model, the Application object has a method, FieldNameToFieldConstant(), that returns a PjField constant for use by the various SetField() and GetField() methods throughout the object model. More information on the SetField Method (and other associated methods) can be found here.
Unfortunately, when using the PSI, there’s no quick way to lookup the Guid for a field. This can be a problem, since the various CustomFieldsRow objects (Task, Resource, Assignment, and Project) do not include the name of the custom field, only the UID (for an example, look at the ProjectCustomFieldsRow entity in the Project 2007 SDK).
Retrieving custom field information in the PSI is accomplished by using the CustomFields web service. The code below is a class that implements a method to retrieve the Guid of a custom field using the field’s name and entity type. I had to chop the code up a lot because of space constraints, so I apologize for the excessive line breaks. This code assumes that you’ve set up a Web Reference to the CustomFields web service named WebSvcCustomFields.
1 using System;
2 using System.Collections.Generic;
3 using System.Net;
4 using System.Text;
5 using System.Windows.Forms;
6 using PSLib = Microsoft.Office.Project.Server.Library;
7
8 namespace EPMFAQ.StephenSanderlin.ProjectServer2007.CustomLookups
9 {
10 public class FieldNameToGuid
11 {
12 #region Methods
13 /// <summary>
14 /// Queries the PSI for a Custom Field matching the given name with
15 /// the proper entity type.
16 /// </summary>
17 /// <param name=”validProjectServerCredentials”>Validated IWA
18 /// Network Credentials.</param>
19 /// <param name=”validProjectServerUri”>Valid Project Server
20 /// Uri.</param>
21 /// <param name=”validProjectServerCookie”>Cookie issued by
22 /// Project Server upon login.</param>
23 /// <param name=”customFieldName”>String representing the name of
24 /// the custom field we wish to retrieve the GUID for.</param>
25 /// <param name=”desiredEntityType”>GUID of the desired
26 /// entity type. Retrieve from
27 /// Microsoft.Office.Project.Server.
28 /// Library.EntityCollection.</param>
29 /// <returns>Guid.Empty if nothing is found or a GUID representing
30 /// the field.</returns>
31 /// <example>GetFieldNameUsingGuid(Credentials, Uri,
32 /// CookieContainer, “Project Origin”, new
33 /// Guid(Microsoft.Office.Project.Server.Library.
34 /// EntityCollection.Entities.ProjectEntity.UniqueId))</example>
35 public static Guid GetGuidUsingFieldName
36 (NetworkCredential validProjectServerCredentials,
37 Uri validProjectServerUri,
38 CookieContainer validProjectServerCookie,
39 string customFieldName, Guid desiredEntityType)
40 {
41 WebSvcCustomFields.CustomFields _cf =
42 new WebSvcCustomFields.CustomFields();
43 const string _cfUrl = “_vti_bin/PSI/CustomFields.asmx”;
44 PSLib.EntityCollection _entityType =
45 new PSLib.EntityCollection();
46 Guid _returnedGuid = Guid.Empty;
47 WebSvcCustomFields.CustomFieldDataSet _cfDataSet =
48 new WebSvcCustomFields.CustomFieldDataSet();
49 WebSvcCustomFields.CustomFieldDataSet.CustomFieldsRow
50 _cfRow;
51 PSLib.Filter _cfFilter = new PSLib.Filter();
52 PSLib.Filter.FieldOperationType _equal =
53 PSLib.Filter.FieldOperationType.Equal;
54
55 string _tableName =
56 _cfDataSet.CustomFields.TableName;
57 string _nameColumn =
58 _cfDataSet.CustomFields.MD_PROP_NAMEColumn.ColumnName;
59 string _uidColumn =
60 _cfDataSet.CustomFields.MD_PROP_UIDColumn.ColumnName;
61 string _entityUidColumnName =
62 _cfDataSet.CustomFields.MD_ENT_TYPE_UIDColumn.ColumnName;
63
64 try
65 {
66 _cf.Credentials = validProjectServerCredentials;
67 _cf.Url = validProjectServerUri.AbsoluteUri + _cfUrl;
68 _cf.CookieContainer = validProjectServerCookie;
69
70 // Set up the filter
71 _cfFilter.FilterTableName = _tableName;
72 _cfFilter.Fields.Add
73 (new PSLib.Filter.Field(_tableName, _nameColumn));
74 _cfFilter.Fields.Add
75 (new PSLib.Filter.Field(_uidColumn));
76 _cfFilter.Criteria =
77 new PSLib.Filter.LogicalOperator
78 (PSLib.Filter.LogicalOperationType.And,
79 new PSLib.Filter.FieldOperator
80 (_equal, _entityUidColumnName, desiredEntityType),
81 new PSLib.Filter.FieldOperator
82 (_equal, _nameColumn, customFieldName));
83
84
85 _cfDataSet =
86 _cf.ReadCustomFields(_cfFilter.GetXml(), false);
87
88 // We should only get one result back
89 if (_cfDataSet.CustomFields.Rows.Count == 1)
90 {
91 _cfRow = (WebSvcCustomFields.
92 CustomFieldDataSet.CustomFieldsRow)
93 _cfDataSet.CustomFields.Rows[0];
94 _returnedGuid = _cfRow.MD_PROP_UID;
95 }
96
97 else
98 {
99 return Guid.Empty;
100 }
101 }
102
103 catch (System.Web.Services.Protocols.SoapException ex)
104 {
105 MessageBox.Show(ex.Message.ToString(), “SOAP Error”,
106 MessageBoxButtons.OK, MessageBoxIcon.Error);
107 }
108
109 catch (System.Net.WebException ex)
110 {
111 MessageBox.Show(ex.Message.ToString(), “Web Error”,
112 MessageBoxButtons.OK, MessageBoxIcon.Error);
113 }
114
115 return _returnedGuid;
116 }
117 #endregion
118 }
119 }
The GetGuidUsingFieldName() method takes five parameters (validProjectServerCredentials, validProjectServerUri, validProjectServerCookie, customFieldName, and desiredEntityType) that supply the necessary information. This method returns a Guid, which is the Guid of the requested field. If no field exists, an empty Guid will be returned.
First, we set up our various local fields on lines 41-62 (including setting up a field to represent the Equal operation type for a filter on lines 52-53). We set up fields to hold column and table names in the CustomFieldDataSet on lines 55-62. While lines 54-61 are not strictly necessary, this is a personal habit — I do this only to make the later method calls more succinct.
We configure the Web Reference on lines 66-68, and then begin to set up the filter parameters. Basically, we are constructing a filter to return only results with the desired custom field name and entity type.
Then, on lines 85-86, we call the ReadCustomFields method in the CustomFields web service. We should recieve only one entry back — if we recieve multiple rows (or none at all), we return an empty Guid. Obviously, in production code, we would want some more robust error handling here, but that is left as an exercise to the reader. Assuming we recieve only one result, we extract the Guid on lines 91-94 and return it on line 115.
This method provides a quick way to retrieve the Guid of a field, thereby approximating the FieldNameToFieldConstant() in the Object Model.
When implementing this code, it’s important to remember that constantly going to the PSI is an expensive process. You do not want to call this method every single time you need a Guid for a field. Therefore, I would recommend that you implement a form of the Lazy Initializtion design pattern which would check a Hashtable (using the field name as the key, and the Guid as the value) that stores the name and Guid of the fields your application uses. You can then simply check the Hashtable to see if the value has been retrieved — if it has not, then you would use the above code to retrieve it and then store it in the hashtable. If your application is long-running, you will want to implement some sort of periodic verification to make sure the Guid you’ve retrieved is still valid. A slight variation of the above code would accomplish this easily. The other obvious alternative is to front-load the retrieval during application startup. While the method discussed above is the more “elegant” solution, front-loading is entirely adequate. However, I would recommend that you spawn off another thread to get the data rather than holding up your startup process.
However you choose to implement the above code, it is a significantly more robust alternative to hardcoding in the Guids.
As always, please feel free to post any comments, feedback, errors, or issues in the EPMFAQ Blog Posts Forum.
He is actively posting new content at ProjectServerHelp.
Popularity: 52%
Discuss this post on the EPMFAQ Blog Posts Forum.

[…] Stephen Sanderlin wrote an interesting post today on Retrieve the Guid of a Custom Field Using its NameHere’s a quick excerpt2 using System.Collections.Generic;. 3 using System.Net;. 4 using System.Text;. 5 using System.Windows.Forms;. 6 using PSLib = Microsoft.Office.Project.Server.Library;. 7. 8 namespace EPMFAQ.StephenSanderlin.ProjectServer2007. … […]
[…] best way to get them is to use the CustomFields web service. I have some sample code posted here: http://www.epmfaq.com/ssanderlin/pro…using-its-name — Stephen Sanderlin Principal Consultant MSProjectExperts For Project Server Consulting: […]