Karine Bosch’s Blog

On SharePoint

Microsoft Flow – Get to the documents from a Teams library in a dynamic way

Last week I had to build a Flow that copies signed documents from a Microsoft Team library to a document library of a SharePoint team site. The customer wants to keep all signed contracts into one place before archiving the Microsoft Team.

The input of the Flow is the name of the Team that needs to be inspected for signed documents.

The Get files action requires following input:

  • The URL to the SharePoint site where the files are stored
  • The guid of the library where the files are stored

HTTP request to get the Teams

To retrieve the Teams from Flow, we can use the Microsoft Graph API. Teams can be retrieved by using the following endpoint:

https://graph.microsoft.com/beta/groups

To retrieve one single Team, we use a filter:

$filter=displayName eq'variables(TeamsName)'

Before the HTTP request will execute successfully, we need to foresee authentication. I registered an app in Azure Active Directory and granted application rights to at least “Read all groups”.

There are a lot of tutorials online that explain how to register an app with Azure AD and how to grant permissions to the several APIs.

I stored the following data needed by the HTTP request in variables:

  • The tenant ID of your O365 tenant
  • The Client ID (of the app registered in Azure AD)
  • The Client Secret (which is the key that has been granted to your app during registration)

The action I used, is an HTTP request:

When this action executes successfully, I can parse the resulting JSON that contains the Id of the Team:

And store the Id of the Team into a variable.

HTTP request to get to the URL of the SharePoint site

The Get Files action requires two parameters: the Site Address and the ID of the document library.

Executing the following call to the Graph API will return the URL to the SharePoint site behind the Teams:

https://graph.microsoft.com/beta/groups/variables(TeamsId)/sites/root/WebUrl

We execute this call in a second HTTP request action:

We parse the JSON to isolate the URL of the SharePoint site behind the Team.

HTTP request to get the ID of the document library of the Team

Now we need to get to the document library behind the Team. Therefore we first need to retrieve the ID of the SharePoint site. (We cannot get to the document library based on the URL of the SharePoint site, wich we retrieved in the previous step).

Executing the following call to the Graph API will return the URL to the SharePoint site behind the Teams:

https://graph.microsoft.com/beta/groups/variables(TeamsId)/sites/root/Id

We execute this call in a HTTP request action:

Now we have the id of the SharePoint site behind the Teams. This ID looks something like this:

<tenant>.sharepoint.com,776e26ce-c949-4d33-a6e2-90dbe4c45f04,10a23c2e-49ee-4e3d-80f9-f534b978dbfe

(Not a single GUID we are used to).

Again we need to parse the resulting JSON in order to isolate the id of the SharePoint site.

With this ID, we can execute another call to the Graph API to get to the document library:

https://graph.microsoft.com/v1.0/sites/output('<site id>') /lists?$filter=displayName eq 'Documents'

The HTTP action looks like this:

Where value is the outcome of the Parse JSON action right before.

The resulting JSON contains the Id and the URL of the document library. We parse the resulting JSON again in order to isolate the ID of the document library.

Now we have all the variables to configure the Get Files action to retrieve the documents in the document library of the Teams.

Executing the Get Files action will also return the folders in the document library. How to filter out the files, and how to filter out the name of the channel to which the document belongs, will be subject to a next post.

November 18, 2018 Posted by | Flow, Graph, Teams | Leave a comment

Microsoft Flow – Create a Document Set

Currently Microsoft is working on the modern view for document sets. The release is foreseen beginning 2019. Currently we are not able to attach a Flow to a document set. Perhaps that’s coming too beginning next year. But in the meantime, you have to find a work around to start your Flow.

You can create a PowerApp that asks you for the metadata of the document set. In my case the requirement of creating a document set during a Flow is just part of a bigger ask, but for the purpose of this blog post, I created a document in the root of my document library to kick off the flow: I select the document, click on the Flow button and choose my flow “Create document set”.

I found the information for this Flow in many posts scattered over the internet. Therefore I decided to write a blog post specifically dedicated to creating Document sets through Flow.

Steps to create this flow:

  • Ask the user for input
  • Get the ID of the list document set
  • Create the document set
  • Update the properties of the document set

Ask the user for input

When the user starts the flow, I show a launch panel to capture the metadata of the document set.

This is achieved by adding output fields to the “For a selected item” step.

Name of the document set and project code are text fields, but the Start date should be a DateTime field, but unfortunately, that doesn’t exist (yet) in Flow. Therefore, my 3 output fields are defined as Text fields.

Get the ID of the list document set

When a content type is added to a list or document library, SharePoint creates a copy of that content type. Therefore we need to retrieve the ID of the list content type in order to be able to create a document set based on that content type.

This step can only be achieved by executing a GET request against the REST api of SharePoint Online. Therefore I added a “Send an HTTP request to SharePoint” action to my flow.

Important info to pass in this action:

  • Use the GET method to retrieve data
  • The GET method needs to be executed against the current site URL
  • To retrieve the ID of a list document set content type, use the following URI, where the filter is set to the name of the content type you want to retrieve:
_api/web/lists/getbytitle('Documents')/contenttypes?$filter=Name%20eq%20%27Project%20Document%20Set%27
  • The GET method also needs some headers:
    • Content-Type    application/json;odata=nometadata
    • Accept               application/json;odata=nometadata

The previous step will return a long string of JSON. We need to parse this JSON string to filter out the ID of the desired content type.

To parse the JSON, I added a “Parse JSON” action. This action asks for the definition of the payload. In a post of my dear friend Serge Luca he explains the easiest way to find out the schema of the payload:

  • Run the flow once (it does not matter if the flow succeeds or fails)
  • Go to the run history of the last run of the flow
  • Expand the step that executes the HTTP GET request to the REST API
  • Copy the JSON in the OUTPUTS section

  • Go back to the flow in Edit mode and expand the”Parse JSON” step.
  • Place your cursor in the text box next to Content.
  • Select the Body object from the Dynamic content popup.

  • I renamed the step to ParseDocumentSetContentType
  • Click the “Use sample payload to generate schema” link

  • Paste the copied JSON into the popup dialog and click Done.

The payload schema will be constructed based on the sample payload you pasted in.

Somewhere in that payload the ID of the document set content type is returned. Now we need to filter that ID out. As you can see in the schema, there is a value property of type array. This means that the value property contains a number of properties like f.e. Description, but also the StringId which is the string representation of the content type ID.

Perhaps there is another way to get to the StringId property, but this is how was able to isolate the StringId:

  • I added a Compose action to get the value property.
  • In the Expression tab of the Dynamic content popup I added the following expression:
first(body('ParseDocumentSetContentType')['value'])

  • I added another action Apply to each to loop through all properties in the value array.
  • After having selected the value object from the Dynamic content popup, I added an additional Compose action inside the Apply to each action to get to the StringId.
  • I was able to select that from the Dynamic content popup under the section ParseDocumentSetContentType:

  • I renamed this action to GetDocumentSetId, as I need the output from this action in a later step.

Create the document set

When we create the document set, we need the name of the new document set. This information was entered by the user when launching the flow.

  • I added a Compose action that I rename to DocumentSetName
  • I select the Name document set input value from the Dynamic content popup

This results in the following:

Now that we have all necessary data, we can create the document set. Also this step can only be achieved by using the REST api.

Important info to pass in this action:

  • Use the POST method to create the document set
  • Use the following URI to get to the document library where you want to create the document set:
_vti_bin/listdata.svc/Documents

Update the properties of the document set

We also need to set the metadata of the document set. This metadata was entered by the user when launching the flow. I added a few Compose actions to capture the user input.

When the creation of the document set was successful, a JSON payload is returned to the flow containing the ID of the newly created document set. To get the payload, go to the run history of the flow. You’ll find the payload in the Outputs section.

Make a copy of this payload and return to Edit mode of your flow. Add a Parse JSON action, rename it properly and select the Body from the Send HTTP request to SharePoint to create document set section.

Click the Use sample payload to generate schema link and parse the copied payload.

After clicking the OK button, you’ll have the correct schema.

The last action we have to add is again an HTTP request to SharePoint to update the properties of the document set.

Useful info to pass in this action:

  • Use the POST method to update the document set
  • Use the following URI to get to the document library where you want to create the document set:
_api/web/lists/getbytitle('Documents')/items()
  • Select the variable DocumentSetId from the Dynamic content popup, and drag it between the brackets of items()
  • The POST method also needs some headers:
    • Content-Type          application/json;odata=verbose
    • Accept                    application/json;odata=verbose
    • X-HTTP-METHOD   MERGE
    • If-Match                  *
  • The body needs to be constructed based.
     {
        "__metadata":{
        "type":"SP.Data.Shared_x0020_DocumentsItem" 
     },
        "ProjectCode":""
     }

The value for ProjectCode can be selected in the Dynamic content popup under the section for a selected item.

Tip:

I spent some time in finding out the real __metadata type that needs to be passed in the POST request. When analyzing the payload that comes back from the action “Send HTTP request to SharePoint to create documentset” I thought that the __metadata type was “SP.Data.DocumentsItem”. After several failed runs I added an additional Send HTTP request to SharePoint action to retrieve the document set item based on its ID. That step learned me that the __metadata type is “SP.Data.Shared_x0020_DocumentsItem”.

It took me a few hours to make the flow work correctly. I hope this post can help someone out! Good Luck!

Useful posts that helped me build my solution:

November 8, 2018 Posted by | Flow | 5 Comments