Monthly Archives: March 2015

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.

Retrieve available web templates and create a subsite with Office 365 REST API

When you work with the Office 365 REST API, especially with SharePoint parts of the API, you will probably need at a given time, to create subsites in a site collection.

If you don’t know how to achieve this goal, we will explain in this article how to do it.

How to create a subsite ?

It exists 2 different ways to create subsites in a site collection with REST API. You need to submit an HTTP POST request to one of the following endpoints :

https://<tenant>.sharepoint.com/_api/Web/Webs/Add

http://<tenant>.sharepoint.com/_api/Web/WebInfos/Add

Each endpoint has its own format to submit information to SharePoint to create the site.

In our following example, we will use the first endpoint. If you want more information for the second, please refer to https://msdn.microsoft.com/EN-US/library/office/jj164022.aspx#bk_CreateSite.

To be able to create a site, SharePoint needs some information such as the title, the description, the template and the URL. These information have to be submitted in the body of the HTTP POST request in the following format.

 {
    "parameters":
    {
        "Title":"Sample Team Site",
        "Description":"The description of our new team site",
        "WebTemplate":"STS#0",
        "Url":"SampleTeamSite"
    }
}

As you can see, you have to indicate the name of an available web template. I’m pretty sure that you’re asking yourself, what are the possible values ?

Retrieve the list of available templates

The Office 365 REST API has all the necessary things to retrieve the list of templates available in your Office 365 tenant.

To retrieve the list of these templates, you just have to submit an HTTP GET request to the following endpoint. You need to specify in which language (1033 = English, 1036 = French…) you want to retrieve the templates (with localized titles, descriptions…).

https://<tenant>.sharepoint.com/_api/Web/GetAvailableWebTemplates(lcid=1033)

When you will execute the request above and check the response, you will see a lot of templates. All of them should not be used because they are deprecated, are system templates, etc…

It’s possible to filter the list to only retrieve usable templates by specifying additional parameters in the querystring as you can see below and by using the OData syntax supported by endpoints of the Office 365 REST API.

https://<tenant>.sharepoint.com/_api/Web/GetAvailableWebTemplates(lcid=1033)?$filter=(IsHidden%20eq%20false)%20and%20(IsRootWebOnly%20eq%20false)

In this new request we specify that we don’t want to retrieve hidden templates (IsHidden = false) and templates available for the root site of a site collection (IsRootWebOnly = false).

When you execute the request, you will retrieve a list of desired templates with the following format for each of them.

{
    Description = "A place to work together with a group of people.",
    DisplayCategory = Collaboration,
    Id = 1,
    ImageUrl = "/_layouts/15/images/stts.png?rev=38",
    IsHidden = 0,
    IsRootWebOnly = 0,
    IsSubWebOnly = 0,
    Lcid = 1033,
    Name = "STS#0",
    Title = "Team Site"
}

To create a new site based on a specific template, you just have to get its name in the JSON response (e.g. STS#0 in the sample above).

Retrieve and use a digest token

You’re now able to submit a request with a well-formated HTTP body to create a new subsite but it’s not enough to work.

When you want to execute requests which perform create, update or delete operations, you have to retrieve a digest token and pass it to the HTTP headers of your request.

To retrieve a digest token, you have to submit an HTTP POST request to the following URL.

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

The response for this request is something like what you can see below.

{
    FormDigestTimeoutSeconds = 1800;
    FormDigestValue = "0x1234567890ABCDEF1234567890ABCDEF,14 Mar 2015 20:00:00 -0000";
    LibraryVersion = "16.0.3722.1239";
    SiteFullUrl = "https://<tenant>.sharepoint.com";
    SupportedSchemaVersions =     (
        "14.0.0.0",
        "15.0.0.0"
    );
    WebFullUrl = "https://<tenant>.sharepoint.com";
}

In this response, you have to extract the FormDigestValue, and pass it to your request in a HTTP header named X-RequestDigest.

By default, a digest is valid for 30 minutes (1800 seconds) but you can extract the FormDigestTimeoutSeconds value and add it to the current time to calculate the expiration date (better solution if Microsoft change the default duration in the future).

You’re now able to create a new subsite in a site collection by retrieving the list of available templates, by generating a digest token, and by submitting your creation request to SharePoint with the Office 365 REST API.

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 😉

List subwebs by using the Office 365 REST API requires to have edit rights

Today I was facing a weird issue and I think it can be the same for others people so I decided to share this experience.

For an application which uses the Office 365 REST API (especially the SharePoint REST API), I tried to reduce the rights necessary to run (in the Microsoft Azure Portal).

The initial configuration was the following :

Azure Rights - Initial Configuration

With this configuration, I was able to retrieve data from sites, webs, subwebs, lists, etc…

Because the application doesn’t necessary need to edit the data, I tried to remove the ‘Edit or delete items in all site collections‘ permission as you can see below.

Azure Rights - IssueWith this new configuration, I tried to execute the following request :

https://tenant.sharepoint.com/_api/Web/Webs/

The URL above allows you to retrieve the list of subwebs from the given site.

When I execute this request, I receive the following JSON response which indicates that I’m not authorized to do this action.

{
    error =     {
        code = "-2147024891, System.UnauthorizedAccessException";
        message = "Access denied. You do not have permission to perform this action or access this resource.";
    };
}

But if I try to access https://tenant.sharepoint.com/_api/Web/ to retrieve information (title, server relative URL…) from the current site, everything works fine.

Revert the permissions to the initial configuration has solved the issue but I’m very surprised to see that it’s necessary to have ‘edit‘ permissions to be able to retrieve the list of subwebs.

Hope this will help you if you encounter the same issue  😉