In November 2017, a support article was published how to Troubleshoot Project Online workflows. One described error is “Custom field CUSTOM_FIELD_GUID does not have a value set for project PROJECT_GUID”. There is a special case when reading an Enterprise Custom Field of type Flag, as mentioned in a Note.
Flag fields have one special behavior: You can’t set a default value for this type of fields. The value is blank, until you changed it manually at least one time – even if it is displayed as No on Project Detail Page or in Project client. Therefore, you can’t access this value from within a SharePoint Designer workflow until the first change.
In this case, a workflow will display the following error:
Error text:
Retrying last request. Next attempt scheduled in less than one minute. Details of last request: HTTP BadRequest to https://…...sharepoint.com/sites/pwa/_api/ProjectServer/WorkflowActivities/ReadBooleanProperty(projectId=……….',propertyId='….') Correlation Id: ….Instance Id: ….
Custom field …. does not have a value set for project….
On my request, a workaround was added as a note, what I see a option 1:
Option 1:
There is one drawback with this option: If you are working in multi language environments, a lookup table with yes/no, true/false, … will not satisfy your non-English users.
Option 2:
There is another option, however it requires some more effort within your workflow. The main part is to use REST API to evaluate, if a value is set for a specific field.
- Step 1 – Set Parameters/Variables
- Step 2 – Get internal name for Enterprise Custom Flag field
- Step 3 - Get ECF value for Project using REST and initialize if necessary
Step 1 – Set Parameters/Variables
We need two variables in this case:
- We need a variable to parameterize the name of the ECF of type Flag
Use Action – Core Actions – Set Workflow Variable to set a new variable to your flag field name.In my sample, I named this variable v_ECFFlagName. - We need the second variable as dictionary as Request Header for our REST call. I named my dictionary I want to use as Request Header v_RequestHeaderStandard (in future posts, you will see some different Request Headers and I want to be able to identify them)
Use Action – Core Actions – Build Dictionary to build v_RequestHeaderStandard.
To get the the response in a JSON format we will have to update the Accept and Content-Type http headers of our REST http call:
Accept : application/json;odata=verbose
Content-Type : application/json;odata=verbose
Click on this to add Accept and Content-Type and set value to application/json;odata=verbose for both names.
Click on Variable: dictionary to define a variable with a meaningful name.
In this sample, I use v_RequestHeaderStandard as mentioned above.
Afterwards, it will look like this:
Step 2 – Get internal name for Enterprise Custom Flag field
To get the internal name for your field, you can use https://<YourTenant>.sharepoint.com/sites/pwa/_api/ProjectServer/CustomFields()?$Filter=Name eq '<YourFlagFieldName>'&$SELECT=InternalName.
- Set a local variable (in this case v_RestURL) to above URL. In this sample, I replaced “https://<YourTenant>.sharepoint.com/sites/pwa/” by a lookup Workflow Context– Current Site URL to enable a re-use of this workflow on a different Project Web App. I have also replaced <YourFlagFieldName> by the local variable holding the name of the flag field.
- Use Action – Core Actions – Call HTTP Web Service.
- Use right click on the action Call to open the context menu – Properties. Set following vales:
- Address: local variable with URL as defined previously
- RequestType: HTTP GET
- RequestHeaders: Dictionary variable as defined above
- Feel free to create your own variables for the other properties:
- Get the internal name from Response Content dictionary and write to a local variable. Use Action – Core Actions – Get an Item from a Dictionary to retrieve value.
Use d/results(0)/InternalName to get the name and write output to another variable (v_InternalName) - Later on, we will need “_” replaced by “_x005f_” in the InternalName, so we will replace this string immediately.
Finally, it will look like this:
After above steps, v_InternalName will be the internal name as required in the next step and it will look like this:
Step 3 - Get ECF value for Project using REST and initialize if necessary
To get the value of all available fields including custom fields, we have to use following URL: https://<YourTenant>.sharepoint.com/sites/pwa/_api/ProjectServer/Projects('<ProjectId>')/IncludeCustomFields/IncludeCustomFields. To retrieve the value within the workflow, we will need another HTTP Call. For this call, we need a different URL and re-use the variable v_RestURL.
- To set v_RestURL, we will use above URL with some replacement: https://<YourTenant>.sharepoint.com/sites/pwa/ will again be replace by lookup Workflow Context– Current Site URL and <ProjectId> by lookup Project Data – Project UID.
So it will look like this: - Again, we need a HTTP call – identical to the above one – since we are using a local variable as URL. So instead of performing the next steps manually, you can just copy the first HTTP call and paste it here.
- Use Action – Core Actions – Call HTTP Web Service.
- Use right click on the action Call to open the context menu – Properties. Set following vales:
- Address: local variable with URL as defined previously
- RequestType: HTTP GET
- RequestHeaders: Dictionary variable as defined above
- Feel free to create your own variables for the other properties:
- To get the value of any field, we need to get result from Response Content dictionary. Due to data structure, we need to get this in two steps.
- First, we retrieve all data and write to a local variable of type Dictionary. Use Action – Core Actions – Get an Item from a Dictionary to retrieve value.
Use d (yes, only one character)to get the data and write output to another variable of type dictionary (v_ResultSet) - In the next step, we will get the value for the Enterprise flag field and write it to a local variable of type string (v_String). Again we need to use Get an Item from a Dictionary. For item by name or path, we use the local variable holding the InternalName, in this sample v_InternalName. As dictionary, we use dictionary v_ResultSet from previous step.
Note: For output, we need to use a variable of type string, not boolean. With a variable of type boolean, we could not evaluate, if there is a value set.
Now, v_String has the value of the Enterprise Flag field and we can check the value. - Now we have to find out, if there is a value set for our flag field. Due to a lack of functions in SharePoint Designer workflows, we replace the value of v_String with v_String^.
- Using a uncommon character like “^”, we can look for this character to identify, if there is a value, using Find substring in string. The local variable v_Integer will hold the first occurrence of “^”.
- If v_Integer = 0, there is no value set for the Enterprise flag field. In this case, the field value can be set to No– since an empty field is displayed to the user anyway. To make this value available in following steps in the workflow, this change hast to be published. Publish of summary information is sufficient in this case.
Finally, it will look like this:
With the above actions, Step 3 will look like this:
Just a note at the end: The same applies for Project Server 2016 (and presumably for Project Server 2013 – but I have not tested with this version).