Category : Workflow

This Sharepoint Designer REST call fetches the manager associated with a user (in this case the person who has initiated the workflow), but it can also be used to get any other attribute associated with the user. The statements shown below have all been included in a single app step in the workflow (Make sure you read the Notes at the end of this blog)

Build a dictionary for a REST call

Add a ‘Build Dictionary’ action as show in the image below

(When you add the ‘Build Dictionary’ action, the system will initially have ‘this‘ instead of the bracketed ellipsis ({…}). Click on ‘this‘ to add the Names ‘Accept’ and ‘Content-Type’ both with the value ‘application/json;odata=verbose‘ as shown below

Set the string that you will use for the rest call

Create a string that you will contain the rest call that you will make as follows

This tells the system that the property we wish to retrieve is the ‘Manager’ (This is what we are retrieving in this example, but this could also be any of the other user properties such as ‘Department’, ‘PreferredName’, ‘PictureURL’ or any of the others. Search on the web for other properties or visit https://technet.microsoft.com/en-us/library/hh147510.aspx to get a list of a few of the properties)

@v=’[%Workflow Context:Initiator%]’

The user whose manager you wish to get (Note the single quotes). I used the ‘Workflow Context’ Data Source to get the Login name of the user who initiated the workflow, but you can use the ‘Created By’ value or a string value that is defined in the following format:

i:0#.f|membership|username@contosa.com

Change certain reserved characters in the string

The user name has certain properties that need to be ‘translated’ for the rest call to work properly. Use the ‘Replace’ action in Designer to substitute i:0#.f with i%3A0%23.f in the string ‘String01′ (this is simply replacing the characters with their encoded ASCII value)

Write the final string to the log

To make sure that you the correct expression has been defined, write the final string to the log as shown below

Call the REST service with the string you have defined

Insert a ‘Call HTTP Web Service’ action as shown below.

Some things about this call.

The original ‘this‘ was changed to the following:

Also, click on the down arrow of the action, select properties and then set ‘RequestHeaders to the dictionary variable you created earlier (Header) as shown below

Get the Managers name (or other property)

Insert a ‘Get an item from a dictionary’ action to fetch the name of the manager (or other data requested) as shown below where I re-use the ‘String01’ variable to contain the result. The result is in the same format as the user login name you used in the REST request (i:0#.f|membership|username@contosa.com)

The actual statement ‘Get‘ statement is ‘d/GetUserProfilePropertyFor‘ if you want to copy and paste.

Display the value that you you have retrieved to make sure it is what was expected

Display any errors that have been returned (See Workflow – Troubleshooting REST calls for troubleshooting any issues)

Notes

You need to at least have ‘Read’ rights on the social tenant. See Workflow – Scoping the App Step on how to set this up, but in short your ‘Permission Request XML’ should look similar to the following (The second line allows your workflows to update any data in the site collection, while the third line allows you access to the social data):

This REST call is useful for listing and deleting the list views. Be aware that the RAW call from a browser returns ALL Views, including Personal ones, while in SharePoint Designer only the public views are returned. Go figure! Nevertheless, here are the steps to list and delete Public Views

Define your Request Header dictionary

Add a ‘Build Diictionary’ action to create the header dictionary that specifies that the REST call must return data in JSON format. Create the Names ‘Accept’ and ‘Content-Type’ setting them both to the String value ‘application/json;odata=verbose’.

Click on ‘this’ and use the ‘Add …’ button to define the dictionary names ‘Accept’ and ‘Content‑Type’ as follows:
Both of these items have exactly the same value ‘application/json;odata=verbose’

Instead of using the defaulted name of ‘dictionary’ in the ‘Output to’ command, I use my own name of ‘Header’. This change of name is optional. At any rate, after the dictionary changes have been made, the command looks similar to the following:

Define the dictionary that will be used to delete the views

Since we will also be deleting certain views in this process, we need to add a dictionary that specifies the elements to delete. Create a name called ‘X-HTTP-Method’ and set the value to ‘DELETE’ . Once defined, change the name of the dictionary to ‘DeleteHeader’

Build the REST Call string

Build the string that will return all the views. This is performed in 2 steps since the SharePoint Designer has an issue when the contents exceed 255 characters

Log the string that you have formulated to help if troubleshooting is necessary

Make the HTTP (Rest) call to the Web Service with the string that you have previously defined

We are still not finished with the web service call yet. Click on the right combo-box of the ‘Call’ action and select ‘Properties …’ and then set ‘RequestHeaders’ to the ‘Header’ dictionary previously defined

Get the results of the call

The rest call returns all the data into the ‘ResponseContent’ variable. Move the results into the a new dictionary variable called ‘ItemData’ so that you can count the number of items returned

Count the number of items so that we know how many views have been returned and store the value in a Workflow Variable called ‘CountOfItems’

Log the Response received from the call to assist in troubleshooting if necessary

Loop through the views returned

Initialize the variable you will use for looping through the views returned by the REST call

Create a loop for the number of items returned by the REST call

Get the Title of the returned item (View) for the current iteration and move it into the workflow string variable ‘ViewName’

Log the Title for troubleshooting purposes if needed

In my case, I only wish to delete specific views so I check a condition to make sure the view returned matches my parameters (For some reason, there are hundreds of views that have been created – not by the users but from somewhere else. This is a problem that Microsoft are investigating at the time of writing)

Get the Id of the view (this is the GUID) and save it in the Workflow Variable ‘ViewID’

Make the HTTP (REST) Call. Set this up as you did previously but click on the ‘Properties…’ and set the ‘RequestHeaders’ to the ‘DeleteHeader’ dictionary defined previously.

Check the Response code. If the delete was successful (ResponseCode = ‘OK’) write to the log and If the response was unsuccessful, get the error data returned and log the values to assist in troubleshooting

Increment the counter so that we read the next row when the loop iterates

That is the end of the loop and the end of the process. The system should now run through the views and delete the ones selected

Final code

The entire code section is as follows (See next page for remaining screen dump. The ‘Update item in ‘Current Item’ statement is not needed):

In many emails it is helpful if the user can click on a link to open the document directly. To enable this functionality is a simple process in SharePoint

Adding a link to display the document

Insert a ‘Send an Email’ action in the workflow

Insert the Current items ‘Encoded Absolute URL’ into the body of the email as shown below

Make the link user friendly

While the link will work, the actual information displayed does not entice the user to click on the link and it may be necessary to include some small HTML coding to make it easier on the eye. Change the Properties of the email by Right clicking on the Action and selecting Properties as shown below

A screen similar to the following will be displayed.

Click on the ellipsis (…) to display the detail (mess) of the body of the email (I have highlighted the ‘Encoded Absolute URL’

After you have made the change, click OK and then OK again to save your changes and exit from the ‘Properties’. Then Click on your email action again and it should now display a friendlier invitation as shown below

(Note the line above the ‘Click here to see the document‘ link. This is useful and can be added using the <HR> tag)

Adding a link to edit the document

To add a link to the email that will open the list item directly in Edit mode, follow the same procedures covered above, but substitute …

We will use this example to define our Designer Workflow statements for adding a user to a group (and once you understand the notation of a REST call, you should be able to apply these steps to post to other URL’s)

Define your Request Header dictionary

Create the dictionary variable with the the Names ‘Accept’ and ‘Content-Type’ setting them both to the String value ‘application/json;odata=verbose’. In this case I called the dictionary variable RequestHeader (In most other posts I called this ‘Header’)

Define your Meta Data dictionary

Create another dictionary variable called ‘MetaData’ and add the name ‘type’ set to the String ‘SP.User’ as follows:

Define your calling parameters dictionary

Create a third dictionary variable called ‘Parameters’ as defined below and add the following names to this dictionary:

__metadata Set this to the dictionary item you created previouslyLoginName Set this to a string of a user account (e.g. i:0#.f|membership|jbloggs@dom.net

Note the double underscores (__) in the name ‘__metadata’. Also, Do not concern yourself if the word ‘Dictionary’ does not appear if you click on the ‘Modify’ button. Your data should look as follows

Log the parameters so that we can see what will actually be passed

Make the call to add the user to the user group

In the call you need to specify the name of the user group you want to add the user to (I used FACUSTOP’ as the group name) and specify the complete URL as follows:

In most cases I want my workflows to run with full-control on the site, so that they can read and update any list mentioned in the workflow, so ALL my stages function within an ‘App Step’. Without this ability, the workflow runs with the rights of the person who initiated it and this can result in a suspended workflow if the individual does not have the rights to read or update a record on a particular table. If this happens, the workflow hangs and no-one is the wiser unless they examine each workflow every day

Microsoft requires that Role ID’s are used when granting permission and although the 10 digit ID’s can be found online, custom permissions are not easily available.

There are two ways to get the Role ID’s

Examine the source code of a raw HTTP statement

After logging into SharePoint, open a Browser window and enter the following after the site name

https://contoso.sharepoint.com/sites/dev/_api/web/roledefinitions

A screen similar to the one below will be displayed.

Select View>Source as shown above and the raw data of the request will appear in a window similar to the following

This represents the raw data returned by the call. You can search for your Permission Level within this viewer, or you can paste this data into an XML Viewer as I have done first, which makes for an easier search as shown in the following image

Actually, this is not much better, but in the highlighted section, you can see that the Role ID for ‘Full Control’ is 1073741829. Now you have your role ID

Execute a REST call directly from the Workflow

Alternatively, you can execute a REST call directly from the workflow to get a role ID of a particular permission level. The complete statements are shown below and then broken down after this image

Set a string variable to the name of the permission level whose Role ID you require.

This statement will get the ‘single’ role ID for the values defined in ‘String02’ – namely ‘Full Control’

Make the REST call

Insert a ‘Call HTTP Web Serice’ action to make the REST call using the value in ‘String01’ as follows:

Make sure that the Request Headers (accessible via the actions properties) isset to a Header Dictionary that has the name ‘Accept’ set to ‘application/json;odata=verbose‘

Update the Current Item.

This is optional and is not required but I use it so I can query the Response returned by the rest call.

For your edification, the REST call will return the following values (shown in JSON format). You can see that all the attributes of the Role are returned, including the Description, ID and RoleTypeKind

This blog will step through all four of these steps to add share access to a particular list item. In the examples that follow, ‘FA Test’/’ListName’ refers to the text name of list you are working with, ‘ListID’ refers to the numeric ID of the list, ‘ItemID’ refers to the numeric ID of the item in the list and ‘UserID’ refers to the numeric ID of the user being granted permission. When working with REST calls, make sure that the Workflow App Permissions are scoped correctly otherwise you could receive an ‘Unauthorized’ response (See Scoping). Also note that you could specify the sharing process in 5 simple steps without having to redefine the Header each time

Many thanks to Jason Lee (Custom Workflow Activity for Granting Permissions on a SharePoint Site) and Bijay Kumar (SharePoint 2013 Add User to SharePoint group using REST API) for sharing their knowledge

Define the header dictionary

This step defines the header format that will be used by all four of the functions mentioned previously.

Create a dictionary variable that will tell the system to return values in JSON format.

Click on ‘this’ and use the ‘Add …’ button to define the dictionary names ‘Accept’ and ‘Content Type’ with both having exactly the same value: ‘application/json;odata=verbose’. I replace the ‘Variable:dictionary’ with my standard ‘Header’ dictionary

Break inheritance on a list (breakroleinheritance)

Since you will be defining custom permissions for the list, you will need to break the role inheritance. This will not change permissions, but will simply change the current users to ‘specified’ rather than ‘inherited’ permissions

Use a ‘Call HTTP Web Service’ action to make the REST call using the string previously defined with an HTTP POST method

We are still not finished with the web service. Click on the right combo-box of the ‘Call’ action and select ‘Properties…’ Set the RequestHeaders to the ‘Header’ dictionary previously created

That is all that is needed to break the role inheritance – no results are returned. Simply check the ‘ResponseStatusCode’ variable to make sure the call functioned correctly

Grant access to the list (addroleassignement)

Once the role inheritance is broken, we need to add the user to the list permissions. Use these actions to give a user or group access to a list (performed prior to granting unique permissions to a list item)

Define the REST call in a string variable

Once you have created the header dictionary, set a workflow variable to the string value of the REST call. In the example shown below, [%Current Item:Created By%] is returning the ‘User Id Number’

principalid: ID of the user or group receiving permissions on the listroleDefId: A role definition ID. The standard Microsoft 10 digit out of the box ID’s are as follows:

Full Control: 1073741829
Read: 1073741826
Contribute: 1073741827

See my post on getting the Role ID values – useful for custom permission definitions

Use a ‘Call HTTP Web Service’ action to make the REST call using the string previously defined with an HTTP POST method

We are still not finished with the web service. Click on the right combo-box of the ‘Call’ action and select ‘Properties…’ Set the RequestHeaders to the ‘Header’ dictionary previously created

That is all that is needed to allow the user to access the list – no results are returned. Simply check the ‘ResponseStatusCode’ variable to make sure the call functioned correctly

Break inheritance on a list item (breakroleinheritance)

You would perform this call prior to granting unique permissions to a list item. This is similar to the call to break inheritance on a list, except that here we specify the list item ID on which to break inheritance

Define the REST call in a string variable

Once you have created the header dictionary, set a workflow variable to the string value of the REST call. In the example shown below, [%Current Item:SourceID%] is returning the ID of the list item

Use a ‘Call HTTP Web Service’ action to make the REST call using the string previously defined with an HTTP POST method

We are still not finished with the web service. Click on the right combo-box of the ‘Call’ action and select ‘Properties…’ Set the RequestHeaders to the ‘Header’ dictionary previously created

That is all that is needed to break the role inheritance – no results are returned. Simply check the ‘ResponseStatusCode’ variable to make sure the call functioned correctly

Share an item with a user

You would perform this call after you have broken permissions on the list and list items and granted the user in question access to the list. These processes were covered in the previous three HTTP Calls)

Define the REST call in a string variable

Once you have created the header dictionary, set a workflow variable to the string value of the REST call. In the example shown below, [%Current Item:SourceID%] is returning the ID of the list item while [%FA Test:Created By%] is returning the ‘User Id Number’

As a beginner I found it difficult to deal with tasks and forms simultaneously. Although the tasks and documents/forms were directly related, the users also found it confusing to switch between the two as they preferred to make any decisions regarding the future direction of the form directly on the form itself. Enter the ‘Wait for field change in current item’ action. From my reading I deduced that workflows in this state have no impact on the overall performance of the site. Not only that, but it simplified my approval flows and form management considerably.

In general terms, this is how I used this action to get updates:

When the workflow reaches a point at which user interaction is required, I use the ‘Update List Item’ action to set two variables in the Form/SharePoint list item; the Boolean field ‘Continue’ is set to false and the integer field ‘Outcome’ is set to 0.

Generally, although this is not shown in this example, it is at this point I also write the account ID’s to a field that specifies who is entitled to perform the update. Because the view of the form is set to have this People field filtered to ‘[Me]’, this item will only appear to the users that need to perform the interaction (In many of my SharePoint sites, I do not allow the user to change the form in these libraries. I also validate within the form itself if the user has rights to view the data)

In the next statement in the workflow, I add the ‘Wait for field change in current item’ action as follows:

The workflow then remains paused until a valid user interacts with the form and sets the field Completed to yes. This is done within the form itself and the action of the Approval button also sets the ‘Outcome’ field so that the option selected in the form can be used to decide on the flow within the workflow

In the statements that follow the ‘Wait for’, I generally log the name of the user who updated the form as well as the date that the form was updated. I then examine the field ‘Outcome’ to determine what action to take within the workflow

I cannot remember the post that pointed me in this direction. While there are many Web Services that return currency cross rates, the site http://currency-api.appspot.com returns a restricted set of rates for free – all you need is to get an access key. The API is documented and easy to work with, but there some restrictions, namely how many rate requests you can make in a month.

To work with this Web Service:

Get you Free API Access key

Visit ‘http://currency-api.appspot.com/’ and click on the button ‘Get Your Free API Access Key’ . This will open up a new screen where you can sign up for free. Follow all instructions to get your key. The key is important

I then check if the Response code equals OK before I move to the next step. If it is not OK, I know something went wrong in the call, and I email the administrator

Get the exchange rate

The next steps involve getting the rate from the returned response. This is performed using a Get action as follows (remember to get the case correct):

Get rate from Variable:Response (Output to Variable:ExchangeRate)

Finally, you have the exchange rate of EUR to USD to do with as is your wont. Since the API has a restriction on the number of times it can be accessed, I allow the users to specify how often they would like the rate updated and in most cases, they selected a monthly update. But your user may require more up-to-date information so it could be that you have to buy ‘professional’ access to the API

When the REST/HTTP Call to a Web Service is not returning correct results, the reason why may not be immediately obvious. In these cases you may need to interrogate the data returned to discover what went wrong

Check the Response Status Code

Add a Log action after the rest call to display the value of the ‘ResponseStatusCode’ variable ‘ResponseCode’ as shown below

Check the logged Response Status Code

Run your workflow and check your workflow log. If everything is OK, this will normally return a positive indication such as ‘OK’ or ‘Created’. If there is a problem, it will display something similar to the message shown below:

If it returns a message such as ‘NotFound’ (as shown above) or ‘InternalServerError’ you may need to display the error in more detail, by logging the actual error message to the workflow log. This is done using a ‘Get’ action on the ResponseContent Variable (‘Response’) as follows:

Get odata.error/message/value from Variable:Response (Output to Variable:ErrorMessage)

The field ‘ErrorMessage’ is a workflow variable that I created to store the contents of the error message. Alternatively, you can display the entire ‘Response’ but displaying this value if the length is greater than 255 characters would hang your workflow.

Run the workflow again

Publish and run the workflow again and check your workflow log again. In my case it displayed the following

In my case, the message is saying that it could not find the SharePoint resource ‘GetByNameXXX’.

Aha! – It should be ‘GetByName’ not ‘GetByNameXXX’. I change my workflow to specify ‘GetByName’ instead of ‘GetByNameXXX’ and republish it. When it runs without error, I remove the error message from the workflow and the world is in balance

Other issues

If no error is being generated, it could be that the field names or their assignments are incorrect in the ODATA call. Check the following:

The body of the REST/HTTP call is normally in an ODATA format similar to the following:

Your field names are not in the correct case. If your SharePoint field is ‘Title’, then in the REST call it should be ‘Title’ not ‘title’

Your field names are incorrectly stated in either the select, filter or orderby options. This can sometimes be tricky especially if your SharePoint fields have spaces in them (Not the best practice, but it happens). For example the SharePoint field Form Status must be specified as Form_x0020_Status. To find the real value of the field, open the list and select Library Settings. Scroll down to the field you are interested in and click on it. Then cut the full URL it navigates to and view the last bit after ‘Field=’. This is the internal field name. In my case, Form Status is actually Form%5Fx0020%5FStatus (Note how the system substitutes %5F for underscores and x0020% for spaces)

You have mistakenly used ‘=’ instead of ‘eq’ or vice-versa in your ODATA statement

Your Boolean vales are specified as true or false or yes or no. Boolean values must be specified as 1 for true and 0 for false. To check for records that have the field ‘Active’ equal to Yes, the ODATA statement should contain Active eq 1 and not Active eq Yes

Your Top query option ($top) is not specified and will therefore only return 100 rows. If you expect more, then set ‘$Top’ to the maximum amount you expect (say ‘$Top=500’). At the time of writing, the maximum number of rows returned is 500

Your number values are placed in single quotes (ID eq ‘307’ should be ID eq 307)

When an HTTP Call statement returned more records than expected, I often found that either the names of fields or values was specified incorrectly (Boolean values in ODATA appear to be 1 or 0 instead of true or false for example, or perhaps the field name was misspelled or used spaces instead of the substitution characters)