Monthly Archives: December 2015

Performing a search request with SharePoint REST API throws a Microsoft.SharePoint.Client.UnknownError

Most of Office 365 REST APIs use the OData v4.0 protocol for exchanging and formatting data between the client and the server.

When you develop an application that uses those APIs, you need to add some HTTP headers in all your requests to let the server know that you want to use this protocol version and to specify the desired verbosity of returned metadata as you can see below :

Accept: application/json;odata.metadata=minimal
OData-Version: 4.0

But if you use these HTTP headers with the SharePoint API to perform a search by calling…

POST https://tenant.sharepoint.com/_api/Search/PostQuery

… then you will receive the following error message :

{
  "error": {
    "code":"-1,
    Microsoft.SharePoint.Client.UnknownError",
    "message":"Unknown Error"
  }
}

You could be surprised because if you try to get information about a site collection by calling…

https://tenant.sharepoint.com/_api/Site

… with the same HTTP headers, it works without any issues.

It can look weird but in fact it’s normal.

If you ever call the following URL to retrieve the OData manifest for the SharePoint API…

https://tenant.sharepoint.com/_api/$metadata

… you can see that the API only supports OData v3.0 (cf. MaxDataServiceVersion).

<edmx:Edmx Version="1.0">
  <edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0">
    ...
  </edmx:DataServices>
</edmx:Edmx>

So even if a lot of features in the SharePoint REST API are working with the OData v4.0 headers, you should better use the OData v3.0 headers such as below to avoid such issues :

Accept: application/json;odata.metadata=minimal
DataServiceVersion: 3.0

Microsoft Graph / OneDrive : The resource could not be found

Microsoft Graph gives you access to a large range of features and data (Outlook, Delve, Azure AD…) using its REST API.

Among these features, you are able to retrieve content from the “OneDrive for Business” service associated to your Office 365 account.

To do this, you just have to call the following URL that will return all the items stored in the root folder of your personal document library.

GET https://graph.microsoft.com/v1.0/me/drive/root/children

By calling that URL, the server will return a JSON response such as the following (the response shown here was truncated for brevity) :

{
  value = ({
    @odata.id = "users/31950312-e7dd-44de-bfaa-4d8274e4d6a0/drive/root/children/01ZWNXWXJYRUGTTJRMQZB2L2YE4NQK4CIF",
    createdBy = { ... },
    createdDateTime = "...",
    eTag = "...",
    folder = { ... },
    id = "01ZWNXWXJYRUGTTJRMQZB2L2YE4NQK4CIF",
    lastModifiedBy = { ... },
    lastModifiedDateTime = "...",
    name = "...",
    parentReference = { ... },
    size = 0,
    webUrl = "..."
  },
  {
    @odata.id = "users/31950312-e7dd-44de-bfaa-4d8274e4d6a0/drive/root/children/01ZWNXWXJ3G5EOS6XJRRCJ54PQZQAJIM3H",
    createdBy = { ... },
    createdDateTime = "...",
    eTag = "...",
    folder = { ... },
    id = "01ZWNXWXJ3G5EOS6XJRRCJ54PQZQAJIM3H",
    lastModifiedBy = { ... },
    lastModifiedDateTime = "...",
    name = "...",
    parentReference = { ... },
    size = 0,
    webUrl = "..."
  })
}

This sample has 2 folders with their respective properties. One of the important parts in the response is the parameter named “@odata.id” which is the URL associated to the object, and used by the API to uniquely identify an item.

In the case of a folder, it could have children (folders and files). If you want to retrieve these children, you have to concatenate “/children” to the unique identifier of the item.

With the first folder of the previous JSON response, it should look like this :

GET https://graph.microsoft.com/v1.0/users/.../drive/root/children/01ZWNXWXJYRUGTTJRMQZB2L2YE4NQK4CIF/children

But if you call that URL, you get the following error message :

The resource could not be found.

This message means that Microsoft Graph is unable to process your request. It’s weird because the URL was generated by the server and returned in the JSON response.

So how can you get to access the children of this item ?

Now that we have retrieved the ID for the item (see the ID value in the JSON response), we are able to build our own URL to retrieve its children.

In Microsoft Graph / OneDrive API, each item is accessible through an URL such as “…/v1.0/users/{user_id}/drive/items/{item_id}”. So if we build our URL by respecting that schema, it works without errors.

In our previous example, the URL to call will be :

GET https://graph.microsoft.com/v1.0/users/.../drive/items/01ZWNXWXJYRUGTTJRMQZB2L2YE4NQK4CIF/children

If you want to play with Microsoft Graph APIs with data stored on your tenant, you can use this site created and hosted by Microsoft : https://graphexplorer2.azurewebsites.net

Set the timezone used for the events in Outlook and Microsoft Graph REST APIs

When you’ve been working for a while like me, you know that when a developer has to work with dates, he faces problems with timezones.

Outlook REST API allows you to get the events for a user by calling the following URL :

GET https://outlook.office365.com/api/v2.0/Me/Events

In the version 2.0 of the API and as you can see in the JSON response below for an event (the response shown here was truncated for brevity), the Start and End items contain two distinct properties for the date and timezone.

By default, all dates and times returned by the server are based on the UTC timezone.

{
  Attendees = (),
  Body = { ... },
  BodyPreview = "...",
  Categories = (),
  ChangeKey = "...",
  CreatedDateTime = "2015-12-02T16:21:57.91403Z";
  End = {
    DateTime = "2012-02-09T19:00:00.0000000",
    TimeZone = "UTC"
  },
  HasAttachments = false,
  Id = "...",
  Importance = "Normal",
  IsAllDay = false,
  IsCancelled = false,
  IsOrganizer = true,
  IsReminderOn = false,
  LastModifiedDateTime = "2015-12-02T16:21:58.7734204Z";
  Location = { ... },
  Organizer = { ... },
  OriginalEndTimeZone = "Pacific Standard Time",
  OriginalStartTimeZone = "Pacific Standard Time",
  Recurrence = { ... },
  ReminderMinutesBeforeStart = 0,
  ResponseRequested = true,
  ResponseStatus = { ... },
  Sensitivity = "Normal",
  SeriesMasterId = <null>,
  ShowAs = "Tentative",
  Start = {
    DateTime = "2012-02-09T18:00:00.0000000",
    TimeZone = "UTC"
  },
  Subject = "...",
  Type = "SeriesMaster"
  WebLink = "...",
  iCalUId = "..."
}

It’s now easier to know what timezone is used for the dates and times. But that’s not all.

If you want the server automatically convert the dates and times of the events into a different timezone, you are able to do so and it’s very easy.

You just have to specify a HTTP header like in the example below to change the timezone. The server will then use this new parameter to return the dates and times in the desired timezone.

Prefer: outlook.timezone="Central Standard Time"

Specifying this HTTP header and calling the previously mentioned URL, you will retrieve a new JSON response like this one :

{
  Attendees = (),
  Body = { ... },
  BodyPreview = "...",
  Categories = (),
  ChangeKey = "...",
  CreatedDateTime = "2015-12-02T16:21:57.91403Z";
  End = {
    DateTime = "2012-02-09T13:00:00.0000000",
    TimeZone = "Central Standard Time"
  },
  HasAttachments = false,
  Id = "...",
  Importance = "Normal",
  IsAllDay = false,
  IsCancelled = false,
  IsOrganizer = true,
  IsReminderOn = false,
  LastModifiedDateTime = "2015-12-02T16:21:58.7734204Z";
  Location = { ... },
  Organizer = { ... },
  OriginalEndTimeZone = "Pacific Standard Time",
  OriginalStartTimeZone = "Pacific Standard Time",
  Recurrence = { ... },
  ReminderMinutesBeforeStart = 0,
  ResponseRequested = true,
  ResponseStatus = { ... },
  Sensitivity = "Normal",
  SeriesMasterId = <null>,
  ShowAs = "Tentative",
  Start = {
    DateTime = "2012-02-09T12:00:00.0000000",
    TimeZone = "Central Standard Time"
  },
  Subject = "...",
  Type = "SeriesMaster"
  WebLink = "...",
  iCalUId = "..."
}

If you want more information about the names of supported timezones, you can find a list on the official documentation on MSDN.

It’s also good to know that even if it’s not mentioned (for now) on the official documentation, this HTTP header also works with Microsoft Graph.

Programmez #191 : Developing C# applications on OSX with Xamarin.Mac

You probably heard about Xamarin for mobile cross-platform development, but do you know that Xamarin also offers a solution to build OSX applications ?

Discover an overview of Xamarin.Mac in my article in the latest issue of Programmez, a magazine available in French-speaking countries (France, Belgium, Switzerland, Luxemburg, Canada…).

Programmez 191