Tag : workflow

Workflow – Useful REST calls – Getting User Properties

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

ip0901

(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

ip0902

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

ip0903

For clarity, the String Builder is as follows:

[%Workflow Context:Current Site URL%]_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertyFor(accountName=@v,propertyName=’Manager’)?@v=’[%Workflow Context:Initiator%]’

Where:

[%Workflow Context:Current Site URL%]

The URL of your site. This is taken from the ‘Workflow Context’ Data Source but could also be hard-coded

_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertyFor(accountName=@v,

This is the method used to get the properties. Enter this as is

propertyName=’Manager’)

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

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

ip0905

Call the REST service with the string you have defined

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

ip0906

Some things about this call.

The original ‘this‘ was changed to the following:

ip0908

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

ip0909

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)

ip0911

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 

ip0912

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

ip0913

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

<AppPermissionRequests>
<AppPermissionRequest Scope=”http://sharepoint/content/sitecollection” Right=”FullControl” />
<AppPermissionRequest Scope=”http://sharepoint/social/tenant” Right=”Read” />
</AppPermissionRequests>


Workflow – Useful REST calls – Listing views (and deleting them)

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’.
202-2

Click on ‘this’ and use the ‘Add …’ button to define the dictionary names ‘Accept’ and ‘Content‑Type’ as follows:
202-3
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:
202-4

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’

214-1

214-2

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

214-3
[%Workflow Context:Current Site URL%]_api/Lists/GetbyTitle(‘Table Name’)/views

214-4
[%String01%]?$Top=500&$Select=Title,Id,ServerRelativeURL

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

214-5

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

214-6

214-7

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

214-8

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

214-9

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’

214-10

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

214-11

Loop through the views returned

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

214-12

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

214-13

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

214-14

Log the Title for troubleshooting purposes if needed

214-15

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)

214-16

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

214-17

 Formulate another REST string – this time to delete the view

214-18

[%Workflow Context:Current Site URL%]_api/Lists/GetbyTitle(‘Table Name’)/views(‘Variable:ViiewID%]’)

Log the string that you have formulated for troubleshooting purposes

214-5

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.

214-19

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

214-20

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

214-21

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

214-22

214-23

 


Workflow – Link from email to list item

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

213-1

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

213-2

A screen similar to the following will be displayed.

213-3

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

213-4

Now, change the highlighted section as follows

213-5

<A href=”[%Current Item:Encoded Absolute URL%]”><FONT color=#0000ff size=2 face=Arial>Click here to see the Document</FONT></A>

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

213-6

(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 …

[%Workflow Context:Current Site URL%]Lists/DOC/EditForm.aspx?ID=[%Current Item:ID%]‘ for ‘[%Current Item:Encoded Absolute URL%]

… in the body of the email, where ‘DOC’ represents the name of the list you are referencing. For example, if the name of the list was ‘Item Prices’, the URL would look as follows:

[%Workflow Context:Current Site URL%]Lists/Item%20Prices/EditForm.aspx?ID=[%Current Item:ID%]

Note that the spaces in the list name need to be substituted by ‘%20’. You may also want to change the hyperlink label to ‘Click here to edit the document’


InfoPath – Consider saving the form and possibly workflow version

In most companies development is ongoing and applications tend to grow horns and tails as users and developers become familiar with existing functionality and require enhancements. This can be a problem especially when working with workflows since although the InfoPath form has changed to the new release, the workflow is still functioning with an older instance. This could mean that functionality in the form is not available in a workflow, since for example, it is only expecting Outcomes 1 through 3, but the form is now providing Outcome 4.

I have found it convenient to develop workflows with the first setting writing the version of the workflow to the SharePoint list (I maintain my own version numbers). That way, when I open the form I will only offer functionality if the workflow version supports it. Alternatively, you can maintain a Form version number and validate against this field

For example, if one only added delete functionality to the system from Version 2.06 onwards, one could create a rule that hid the control so that the user could not select it as shown below

111-1


InfoPath – Restart workflows at different stages

In most of my forms that are linked to workflows, I provide the ability for an administrator to restart the workflow at a particular point if needed. This is not only useful in testing situations (since a workflow can skip time consuming steps if they have already been completed), but it provides much needed flexibility in SharePoint where server throttling situations can result in a suspended workflow which needs to be restarted at a previous point.

In this case I maintain a ‘StartFrom’ combo box in my ‘hidden’ view, that if changed sets a value ‘Restart’ to true. If I need to restart a particular workflow at a specific point, I do the following:

  1. Terminate the current workflow
  2. Open the form, select the hidden view, and set the ‘StartFrom’ to my starting point
  3. I then restart the workflow. The first stage checks if the workflow is being restarted and then uses a series of linked stages to decide the point at which to restart the workflow

InfoPath – Preventing updates to the form when the workflow is updating

This applies to lists that are linked to workflows. Since the workflow and InfoPath form are separate processes, it is possible that users can update the form while the workflow is processing data. This ability to update the form gives the user the impression that the updated data is considered and while this is true in some cases, it can be an issue if the workflow is only initiated when items are added to the list, as the workflow may be running based on previous values

To prevent this from occurring, I use a promoted field called ‘Updating’ in the form to test whether the workflow is in the process of updating. When the workflow is updating information, this value is set to ‘true’. When the user opens the form during this stage, the forms checks this value and if it is set to ‘true’, the updating buttons (such as ‘Approve’ or ‘Reject’) are disabled, thus preventing the user from making any adjustments. Additionally, a message can be displayed to inform the user that an update is happening. I normally set this value in the form itself since I am aware than an update is about to occur. This is necessary as the workflows take time to start, and the user could open and update the form prior to the workflow setting this value

In my workflows whenever an update is required from the user, the promoted field ‘Outcome’ is set to 0 and the field ‘Completed’ is set to ‘false’. When the user selects a button to approve or reject the data, the system sets this value to 1 or 2 and sets another field ‘Completed’ to ‘true’. This indicates that an update has been made (based on the workflow action ‘Wait for Field Change in Current Item’) and the workflow can resume and make decisions using the chosen selection.


Workflow – Use the App Step in workflows

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

To see how to do this, follow the easy to use and comprehensive guidelines given through the Microsoft URL Create a workflow with elevated permissions by using the SharePoint 2013 Workflow platform . Also, take a look at my post on Workflow – Scoping the App Step to specify the scope correctly if you are using sub-sites or wish to access data across the Site Collectiion


Workflow – Useful REST calls – Get Role ID

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.

211-1

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

211-2

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

211-3

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

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

211-6
In this case I am looking for the ‘Full Control’ Role ID

Define the REST call string

Set String01 to the following

211-5
[%Workflow Context:Current Site URL%]/_api/web/roledefinitions([%Variable:String02%])

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:

211-8

211-7

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.

211-9

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

{
“odata.metadata”: “https://jahglobal.sharepoint.com/sites/jkt-dev/_api/$metadata#SP.ApiData.RoleDefinitions/@Element”,
“odata.type”: “SP.RoleDefinition”,
“odata.id”: “https://jahglobal.sharepoint.com/sites/jkt-dev/_api/Web/RoleDefinitions(1073741829)”,
“odata.editLink”: “Web/RoleDefinitions(1073741829)”,
“BasePermissions”: {
“High”: “2147483647”,
“Low”: “4294967295”
},
“Description”: “Has full control.”,
“Hidden”: false,
“Id”: 1073741829,
“Name”: “Full Control”,
“Order”: 1,
“RoleTypeKind”: 5
}

Get the ID of the Role

Use a ‘Get an item from a dictionary’ action to get the ID of the role. This value is stored in the workflow variable ‘ID’ as shown below

211-10

You now have the Role ID in the variable ‘ID’


Workflow – Useful REST calls – Share Item

Four steps are involved in updating share permissions on a list:

  1. Breaking inheritance on the list
  2. Granting access to the list
  3. Breaking inheritance on a list item
  4. Granting access to a list item

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.

203-2202-3

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

203-3

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

Define the REST call in a string variable

210-1
[%Workflow Context:Current Site URL%]_api/web/lists/GetByTitle(‘ListName’)/breakroleinheritance

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

210-2

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

210-3

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’

210-5
[%Workflow Context:Current Site URL%] /_api/web/lists/GetByTitle(‘ListName’)/roleassignments/addroleassignment (principalid=UserGroupID , roleDefId=1073741826)

Set the values in the string builder as follows:

principalid:          ID of the user or group receiving permissions on the list
roleDefId:           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

210-2

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

210-3

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

210-6

[%Workflow Context:Current Site URL%]_api/web/lists/GetByTitle(‘ListName’)/getItemById (ItemID)/breakroleinheritance

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

210-2

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

210-3

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’

210-7

[%Workflow Context:Current Site URL%]_api/web/lists/GetByTitle(‘ListName’)/getItemById(ItemID)/roleassignments/addroleassignment (principalid=UserID, roleDefId=1073741829)

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

210-2

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

210-3

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


Workflow – Using the ‘Wait-for’ instead of tasks

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:

209-1

  1. 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.
  1. 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)
  2. In the next statement in the workflow, I add the ‘Wait for field change in current item’ action as follows:209-2
  1. 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
  1. 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