Tag Archives: Office Graph

Getting all boards to which a document belongs using the Office Graph

If you use Delve in Office 365 (an extension of Office Graph), you should know what are boards, for logically classify your documents, without moving them to a new physical location (document libraries).

Like every services in Office 365, there’s an API to allow developers to create applications around Office 365. If you want more information about how to query the Office Graph in Office 365, you can refer to the following article at MSDN.

If you read the previous article, you will see that there’s no information in the API documentation, on how to know which boards a document belongs.

To achieve this goal, there’s an undocumented action (ID = 1046) you can use to query the Office Graph. This action is used such as the others :

ACTOR(<ActorId>,action:1046)

If you want to know what are the boards for a given document, the ActorId in the syntax above corresponds to the ID of the document. You can get the ID of a document by retrieving the DocId value from the search engine, by using a simple query or a graph query (e.g. for a document from the personal feed of the current user).

If you query the Office Graph with a syntax such as ACTOR(48202211,action:1046), you will get a search result such as below (it was truncated for focusing on the most important part):

Table = {
  Rows = (
    {
      Cells = (
        {
          Key = DocId,
          Value = 4362767297,
          ValueType = "Edm.Int64"
        },
        {
          Key = Path,
          Value = "TAG://PUBLIC/?NAME=FINANCE",
          ValueType = "Edm.String"
        },
        {
          Key = Title,
          Value = Finance,
          ValueType = "Edm.String"
        },
        {
          Key = Edges,
          Value = "[{\"ActorId\":48202211,\"ObjectId\":4362767297,\"Properties\":{\"Action\":1046,\"Blob\":[123,34,84,97,103,78,97,109,101,34,58,34,70,105,110,97,110,99,101,34,125],\"BlobContent\":\"{\\\"TagName\\\":\\\"Finance\\\"}\",\"ObjectSource\":1,\"Time\":\"2015-08-21T11:34:39.0000000Z\",\"Weight\":1}}]",
          ValueType = "Edm.String"
        }
      )
    },
    {
      Cells = (
        {
          Key = DocId,
          Value = 4362767298,
          ValueType = "Edm.Int64"
        },
        {
          Key = Path,
          Value = "TAG://PUBLIC/?NAME=MARKETING+STRATEGY",
          ValueType = "Edm.String"
        },
        {
          Key = Title,
          Value = "Marketing Strategy",
          ValueType = "Edm.String"
        },
        {
          Key = Edges,
          Value = "[{\"ActorId\":48202211,\"ObjectId\":4362767298,\"Properties\":{\"Action\":1046,\"Blob\":[123,34,84,97,103,78,97,109,101,34,58,34,77,97,114,107,101,116,105,110,103,32,83,116,114,97,116,101,103,121,34,125],\"BlobContent\":\"{\\\"TagName\\\":\\\"Marketing Strategy\\\"}\",\"ObjectSource\":1,\"Time\":\"2015-08-21T11:19:06.0000000Z\",\"Weight\":1}}]",
          ValueType = "Edm.String"
          }
        }
      )
    }
  )
}

The search result above indicates that our document (ActorId = 48202211) was added in two boards called “Finance” and “Marketing Strategy“. Each row in the search result corresponds to a board with its properties (retrieved from those that have been specified in the search query).

Getting boards for multiple documents within the same request

As we have seen, it’s pretty simple to retrieve the boards for a single document but what should I do if I want to retrieve the boards for many documents ?

For performance issue it’s not viable to execute a request for each document. So what’s the solution ?

Office Graph lets you to combine many actors in the same request. So if you execute a request such as the one below (each actor corresponds to a document), you will get as response, a search result with the boards for each document.

OR(ACTOR(48204878,action:1046),ACTOR(48204877,action:1046),ACTOR(48202211,action:1046))

Good, but how can I know which document is associated to which board ?

If you paid attention to the search result, there’s a property called “Edges” for each row. The value of this property is a JSON string that has been serialized.

If we deserialize and format those values, they look like this:

Edges for row #1
[
  {"ActorId":48204878,"ObjectId":4362767297,"Properties":{"Action":1046,"Blob":[123,34,84,97,103,78,97,109,101,34,58,34,70,105,110,97,110,99,101,34,125],"BlobContent":"{\"TagName\":\"Finance\"}","ObjectSource":1,"Time":"2015-08-21T11:18:52.0000000Z","Weight":1}},
  {"ActorId":48202211,"ObjectId":4362767297,"Properties":{"Action":1046,"Blob":[123,34,84,97,103,78,97,109,101,34,58,34,70,105,110,97,110,99,101,34,125],"BlobContent":"{\"TagName\":\"Finance\"}","ObjectSource":1,"Time":"2015-08-21T11:34:39.0000000Z","Weight":1}},
  {"ActorId":48204877,"ObjectId":4362767297,"Properties":{"Action":1046,"Blob":[123,34,84,97,103,78,97,109,101,34,58,34,70,105,110,97,110,99,101,34,125],"BlobContent":"{\"TagName\":\"Finance\"}","ObjectSource":1,"Time":"2015-08-21T20:50:40.0000000Z","Weight":1}}
]

Edges for row #2
[
 {"ActorId":48204877,"ObjectId":4362767298,"Properties":{"Action":1046,"Blob":[123,34,84,97,103,78,97,109,101,34,58,34,77,97,114,107,101,116,105,110,103,32,83,116,114,97,116,101,103,121,34,125],"BlobContent":"{\"TagName\":\"Marketing Strategy\"}","ObjectSource":1,"Time":"2015-08-21T20:50:35.0000000Z","Weight":1}},
 {"ActorId":48202211,"ObjectId":4362767298,"Properties":{"Action":1046,"Blob":[123,34,84,97,103,78,97,109,101,34,58,34,77,97,114,107,101,116,105,110,103,32,83,116,114,97,116,101,103,121,34,125],"BlobContent":"{\"TagName\":\"Marketing Strategy\"}","ObjectSource":1,"Time":"2015-08-21T11:19:06.0000000Z","Weight":1}}
]

As you can see, it’s an array in which each object corresponds to an actor with some properties.

The important values for each object corresponds to :

  • ActorId ==> The ID of our document
  • ObjectId ==> The ID of the board
  • TagName ==> The name of the board
  • Time ==> When the document was added to the board

In this example in which we queried the Office Graph for three documents, two of them (ActorId = 48204877 and ActorId = 48202211) were added in two boards (“Finance” and “Marketing Strategy“). The third document (ActorId = 48204878) was only added in the “Finance” board.

Introducing the new Office 365 unified API

Build conference was held in San Francisco this week (from April 29th to May 1st) and it was the place to be because Microsoft made a lot of announcements around its ecosystem (Windows 10, Azure, HoloLens, Office 365…).

Among all the news annouced this week, we particularly appreciated the launch (in preview version for now) of the Office 365 unified API. Let’s take a look to this new API.

Why a new API ?

As you probably know, Office 365 offers a lot of features for companies who needs a directory, emails, instant messaging, collaboration, videos, search, social network…

Each of these features are offered by a dedicated product (Azure AD, Exchange, Lync, SharePoint, Yammer, OneDrive for Business…) and it was pretty complicated to develop solutions which are connected with all of them.

Indeed, each product has its own API, accessible through a dedicated endpoint :

It’s to simplify all of this, that the new Office 365 Unified API was created. It allows developers to create solutions which are able to reach the content of each product from a single endpoint.

Office365 Unified API

A single endpoint is more easy to use and it simplifies a lot of tasks such as managing authentication tokens (you need one access token for each endpoint when you use the actual Office 365 APIs).

This new API works like the actual APIs so to use it, you need to :

  • Register you app in Azure AD
  • Define permission scopes and security
  • Authenticate through OAuth 2.0

Office365 Unified API - Registration in Azure

To retrieve data from your tenant and after successful completion of the authentication process, you can send requests to the endpoint as you can see in the following examples.

Me (or other users)

Get information about the current user (the authenticated user) :

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

Get the picture (of given dimensions) for the current user :

https://graph.microsoft.com/beta/me/userphotos/96X77

Get the manager, the subordinates or the groups for the current user :

https://graph.microsoft.com/beta/me/manager
https://graph.microsoft.com/beta/me/directReports
https://graph.microsoft.com/beta/me/memberOf

Get information about another user in your company’s directory  :

https://graph.microsoft.com/beta/contoso.com/users/demo@contoso.com
https://graph.microsoft.com/beta/contoso.com/users/demo@contoso.com/manager
https://graph.microsoft.com/beta/contoso.com/users/demo@contoso.com/memberOf

Messages

Get the email messages for the current user :

https://graph.microsoft.com/beta/me/messages

Get the last 5 message for the current user :

https://graph.microsoft.com/beta/me/messages?$top=5

Get the next 5 messages ordered by creation date :

https://graph.microsoft.com/beta/me/messages?$top=5&$skip=5&$orderby=DateTimeCreated

Calendar / Events

Get the events for the current user :

https://graph.microsoft.com/beta/me/events

Get the events for the current user between the start date and the end date:

https://graph.microsoft.com/beta/me/calendarview?startdatetime=2015-04-01t01:00:00z&enddatetime=2015-04-16t23:00:00z

SharePoint Files / OneDrive Files

Get OneDrive’s for Business files for the current user and get a specific file by using its ID :

https://graph.microsoft.com/beta/me/files
https://graph.microsoft.com/beta/me/files/<id>

Get OneDrive’s for Business files for a given user :

https://graph.microsoft.com/beta/demo@contoso.com/files

Groups

Get the groups (collaboration and not security/distribution) for your company :

https://graph.microsoft.com/beta/contoso.com/groups?$filter=groupType+eq+'Unified'

Get the members, the files, and the conversations for a group by using its ID :

https://graph.microsoft.com/beta/contoso.com/groups/<id>/members
https://graph.microsoft.com/beta/contoso.com/groups/<id>/files
https://graph.microsoft.com/beta/contoso.com/groups/<id>/conversations

Office Graph / Delve

Get the people with whom the current user work with :

https://graph.microsoft.com/beta/me/workingWith

Get the data (documents, email attachments…) which are trending around the current user :

https://graph.microsoft.com/beta/me/trendingAround

What’s coming next ?

In the examples presented in this article, we only saw how to get data but you are already able to perform CRUD operations as you can do it today with other dedicated endpoints.

It’s also good to note that Microsoft has updated its client libraries for .NET, iOS and Android to support the new unified API.

The Office 365 Unified API available today is just the first version (a preview version) and a lot of improvements will be available in the future. New data types will be added in the next few months.

Among some of the improvements already announced by Microsoft during the conference :

  • Tasks
  • Notes
  • Skype
  • Personal Contacts
  • Notifications
  • And much more…

Want to learn more and want to try it ?

The first thing to see if you want to discover the new API (this article was based on it) is the webcast of the session named “Supercharging Your Custom Solutions with the Office 365 Unified API Endpoint” which has been recorded during the Build conference. It’s available on Channel 9 : http://channel9.msdn.com/Events/Build/2015/3-641

If you want to learn more about the new Office 365 Unified API, you can also refer to the official documentation available at http://dev.office.com/unifiedAPIs.

Microsoft has also created/updated some websites if you want to try the new API directly from your web browser:

How to disable Office Graph and what are the impacts on the REST API

On March 16th, Delve (based on Office Graph) has started rolling out to eligible Office 365 business customers worldwide.

This is a great news for all the users who wants a new way to discover and work with their documents stored in their Office 365 tenant.

But because it’s a brand new way to work, all customers doesn’t necessarily want to offer Delve to all their users for now.

Disable Office Graph on the Office 365 tenant

If you don’t want to use Office Graph in your company, it’s possible to disable it for all the users.

To do it and as a tenant administrator, you have to connect to the SharePoint Admin Center then go the “Settings” section.

In this screen, you just need to check “Don’t allow access to the Office Graph” as you can see in the screenshot below.

Disable Office Graph

Then save your modification and after a short time (from few seconds to few minutes), Delve and Office Graph will be disabled/unusable for all the users of your Office 365 tenant.

Querying the Office Graph with the REST API

Now that we are able to enable/disable the Office Graph at the tenant level, let see how to query it by using the REST API and what happens when the feature was disabled.

For now (Microsoft is working to offer new possibilities/APIs in the future), you have to use the SharePoint search API to query the Office Graph. It’s pretty simple and there’s two different ways to achieve this goal.

My favorite is to POST the query to the search endpoint. The endpoint is accessible from all the SharePoint sites on your tenant.

https://<tenant>.sharepoint.com/_api/search/postquery/
OR
https://<tenant>.sharepoint.com/sites/anotherSiteCollection/_api/search/postquery/

Office Graph queries can be very simple or much more complicated to write, depending on what you want to retrieve. Below, you can see a sample which retrieves the documents (Word, Excel, PowerPoint, PDF and Office 365 Videos) as you can see when you display Delve’s homepage.

{
  "request": {
    "Properties": [
      {
        "Name": "GraphQuery",
        "Value": {
          "QueryPropertyValueTypeIndex": 1,
          "StrVal": "AND(ACTOR(ME,action:1021),ACTOR(ME,OR(action:1021,action:1036,action:1037,action:1039,action:1052)))"
        }
      },
      {
        "Name": "GraphRankingModel",
        "Value": {
          "QueryPropertyValueTypeIndex": 1,
          "StrVal": "action:1021,weight:1,edgeFunc:weight,mergeFunc:max"
        }
      }
    ],
    "QueryTemplate": "({searchterms}) AND ((NOT HideFromDelve:True) AND (FileExtension:doc OR FileExtension:docx OR FileExtension:xls OR FileExtension:xlsx OR FileExtension:ppt OR FileExtension:pptx OR FileExtension:one OR FileExtension:pdf OR ContentTypeId:0x010100F3754F12A9B6490D9622A01FE9D8F012*))",
    "Querytext": "*",
    "RankingModelId": "0c77ded8-c3ef-466d-929d-905670ea1d72",
    "RowLimit": 20,
    "StartRow": 0,
    "Timeout": 30000,
    "TrimDuplicates": true
  }
}

If you want more information about how to build an Office Graph query, please refer to the following MSDN article : https://msdn.microsoft.com/en-us/office/office365/howto/query-Office-graph-using-gql-with-search-rest-api

Execute a query when the Office Graph was disabled

You probably ask yourself : what will happen if we execute the previous query on a tenant from which the Office Graph was disabled ?

As for a lot of things when you use the Office 365 REST API, if you try to use an unavailable feature or if you send malformed data, an exception is thrown and returned to the user.

The Office Graph and the SharePoint search engine work as well. If you try to execute an Office Graph query when the feature is disabled, an exception is thrown. You can see below an example of the server response.

{
  "odata.error": {
    "code": "-1, Microsoft.Office.Server.Search.REST.SearchServiceException",
    "message": {
      "lang": "en-US",
      "value": "Graph queries currently disabled."
    }
  }
}

For now, there’s no REST API to check if the Office Graph feature is enabled or disabled. The only way to check is to execute a query and catch the exception.

Search documents and generate a preview with Office 365 REST API

Since Delve and Office Graph were announced last year, you may have asked how it’s working and if it’s possible to retrieve documents from all your SharePoint sites, and not only content from Delve/Office Graph.

Delve - HomePage

In the rest of this article, we are not going be focused on Delve / Office Graph (maybe in a future post) but we’re going to explain how to search any kinds of documents and how to generate a preview for these.

If you’re not familiar with Office 365 REST API, you are able to perform searches on content stored in your SharePoint sites by using the search endpoint.

https://<tenant>.sharepoint.com/_api/search

This endpoint offers 2 different possibilities to submit a query to the SharePoint search index.

For the first one, you just need to submit an HTTP GET request to URL below with some parameters in the querystring.

https://<tenant>.sharepoint.com/_api/search/query?querytext='OneDrive'

This first usage is described by a lot of blogs thus, do a search with Google/Bing if you want more information on this.

The second possibility is to submit an HTTP POST request to :

https://<tenant>.sharepoint.com/_api/search/postquery/

This second choice is more flexible if your search query is complex or very long (remember that an URL cannot exceed ~4000 characters).

Below you can see and example of the body you have to include in your HTTP POST message. (Important : SharePoint is case sensitive when you submit your search query).

{
    request =     {
        Querytext = "(ContentTypeId:0x010100F3754F12A9B6490D9622A01FE9D8F012*)",
        RowLimit = 20,
        SelectProperties =         (
            DocId,
            DefaultEncodingURL,
            DocumentPreviewMetadata,
            SiteId,
            Title,
            UniqueId,
            WebId
        ),
        StartRow = 0,
        TrimDuplicates = True
    }
}

This query will return the first 20 documents from Office 365 Video (based on the ContentTypeId). We only select properties needed (DocId, SiteId, Title…) and want to exclude duplicates.

The StartRow parameter allows you to perform paging if necessary.

There are many more kinds of parameters you can pass to your search query. Refer to the following MSDN page if you need more information : https://msdn.microsoft.com/en-us/library/office/jj163876.aspx

Now that we are able to retrieve a list of documents (Office 365 videos in our case), how to generate a preview for each of them ?

By analyzing how Delve is working, you can see that thumbnails are generated by calling an URL with the following format :

https://<tenant>.sharepoint.com/_layouts/15/getpreview.ashx?guidFile=<GUID>&guidSite=<GUID>&guidWeb=<GUID>&docid=<Int>&metadatatoken=<String>

As you can see, these parameters are similar to those we have put in our search query :

  • guidFile = UniqueId
  • guidSite = SiteId
  • guidWeb = WebId
  • docId = DocId

But what about the metadatatoken parameter ? That’s the magic because we have put a particular property named DocumentPreviewMetadata in our search query.

If you look at the search result response, this property is returned in the following format.

{
    Key = DocumentPreviewMetadata,
    Value = "{\"previews\":[{\"h\":187,\"src\":0,\"w\":300}],\"token\":\"300x187x0\"}",
    ValueType = "Edm.String"
}

As you can see, the value for the property is a JSON serialized object in which you are able to get the width, the height and the token associated to the file preview. If the file has multiple preview (e.g. many slides in a PowerPoint document), the previews array will contain multiple values.

If you deserialize this value and put the token value into the metadatatoken parameter of the URL mentioned previously, you have all the items necessary to call the URL and to generate the preview for all your documents.

Thanks for reading this article and I hope it will help you to develop awesome apps by using the Office 365 REST API 😉