Monthly Archives: November 2015

Be careful to case sensitivity in Microsoft Graph REST API

Last week during Connect(); // 2015, Microsoft announced the general availability (GA) of Microsoft Graph (formerly known as Unified API).

In association with the announcement, a brand new website with a full documentation that explains what’s Microsoft Graph and how to use the REST API was launched here : http://graph.microsoft.io/docs

Since few days, I’m working with Microsoft Graph and I found few issues. Today, I want to talk about one of them which is common with a lot of APIs but frustrating when you encounter it.

During my investigations, I was trying to send a mail and by refering the documentation, it’s noted that you just have to send a JSON message like this one…

["message": {
  body = {
    content = "This message was sent with Microsoft Graph",
    contentType = "text"
  },
  importance = "high",
  subject = "Microsoft Graph REST API",
  toRecipients = ({
    emailAddress = {
      address = "john@doe.com",
      name = "John Doe"
    }
  })
},
"saveToSentItems": false]

… to the following URL.

https://graph.microsoft.com/v1.0/me/microsoft.graph.sendMail

Very easy in theory but when I execute the request with these values, I receive the following error message.

One or more parameters of the operation 'SendMail' are missing from the request payload. The missing parameters are: Message.

To understand what’s the problem, I looked at the metadata generated for the REST API (based on OData 4.0) by accessing the following URL.

https://graph.microsoft.com/v1.0/$metadata

In the metadata returned by the server, you can see this.

<Action Name="sendMail" IsBound="true" EntitySetPath="bindingParameter">
<Parameter Name="bindingParameter" Type="microsoft.graph.user" />
<Parameter Name="Message" Type="microsoft.graph.message" Nullable="false" />
<Parameter Name="SaveToSentItems" Type="Edm.Boolean" />
</Action>

As you can see, the parameters used by this method are named “Message” and “SaveToSendItems” (in PascalCase) and not “message” and “saveToSendItems” (in lowerCamelCase) as written in the documentation.

When you pay attention to metadata generated by OData, you will see that some methods, especially those existing in other parts of Office 365 REST APIs (e.g. sendMail is used in Outlook REST API), still use PascalCase for their parameter names.

So if you follow the documentation to implement Microsoft Graph but you receive an error message indicating that a parameter is missing, take a look at metadata generated by OData to validate that the method is not expected to use PascalCase instead of lowerCamelCase for its parameters.

An SSL error has occurred when trying to use the Outlook REST API on iOS 9 or OSX 10.11 (El Capitan)

In a previous article, we talked about an issue when you try to stream an Office 365 Videos from Azure Media Services in your application running on iOS 9.

It seems that Microsoft is actually doing some modifications on the infrastructure of the Office 365 platform, especially around the SSL certificates, because today I’m facing the same error when using the Outlook REST API.

I’m trying to call the following URL which should return the last 10 messages stored in the inbox  of the authenticated user :

https://outlook.office365.com/api/v2.0/Me/MailFolders('Inbox')/Messages

But I get the following error message, which indicates there’s an issue with SSL certificates :

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."
UserInfo={NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSUnderlyingError=0x7d96cd90 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorCodeKey=-9802, _kCFStreamErrorDomainKey=3, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x7afb9d50>, kCFStreamPropertySSLPeerCertificates=<CFArray 0x7ae63490 [0xa97098]>{type = immutable, count = 2, values = (
 0 : <cert(0x7afb8570) s: outlook.com i: Microsoft IT SSL SHA1>
 1 : <cert(0x7afb96d0) s: Microsoft IT SSL SHA1 i: Baltimore CyberTrust Root>
)}}}, _kCFStreamErrorCodeKey=-9802, NSErrorFailingURLStringKey=https://outlook.office365.com/api/v2.0/Me/MailFolders('Inbox')/Messages, NSErrorPeerCertificateChainKey=<CFArray 0x7ae63490 [0xa97098]>{type = immutable, count = 2, values = (
 0 : <cert(0x7afb8570) s: outlook.com i: Microsoft IT SSL SHA1>
 1 : <cert(0x7afb96d0) s: Microsoft IT SSL SHA1 i: Baltimore CyberTrust Root>
)}, NSErrorClientCertificateStateKey=0, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x7afb9d50>, NSErrorFailingURLKey=https://outlook.office365.com/api/v2.0/Me/MailFolders('Inbox')/Messages}

The cause of this error is still the same as explained in our previous article : App Transport Security (ATS).

To solve the issue, you need to add some lines in your Info.plist to configure ATS to ignore the SSL error.

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains<key>
  <dict>
    <key>outlook.office365.com</key>
    <dict>
      <key>NSExceptionRequiresForwardSecrecy</key>
      <false/>
    </dict>
  </dict>
</dict>

You can also edit this file using the editor in Xcode rather than manually edit the XML file :

Office365 Outlook REST API - App Transport Security

Searching documents across multiple Office 365 groups with REST API

If you work on Office 365, you probably know what are groups, one of the latest features launched by Microsoft on its collaborative platform.

For those who don’t know what’s it, it’s a new way and mostly a simplest way, to create sites that allow users to collaborate with a minimal set of collaborative features such as storing documents, creating conversations, taking notes in a notebook and sharing events on a calendar.

Below you can see an example of a group, especially the document storage.

Office365 - Groups

For now, if you want to find a document in a given group or a set of documents across all groups, there’s no possibility to search what you’re looking for.

Indeed, when you search for documents using the search area available on the top-left (cf. screenshot), you will be redirected to the global search center of your company available in Office 365.

Fortunately, we can use the search engine with REST API to implement that missing feature.

As a reminder (we described it many times in articles on this blog), to submit a search query in Office 365 using REST API, you can send a POST request to the following URL with a well-formatted HTTP body.

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

When you want to retrieve only documents stored in SharePoint libraries, you can filter items based on the ContentClass property which exists for each items (pages, documents, tasks, events…) that were created in your sites.

In the same way, if you want to search only in a particular kind of site (e.g. Office 365 groups in our case), you can filter results based on the SiteTemplate property.

So what looks like the request to send to the REST API ?

{
  request = {
    Querytext = "ContentClass:STS_ListItem_DocumentLibrary AND SiteTemplate:GROUP",
    RowLimit = 100,
    SelectProperties = (
            Title,
            DefaultEncodingURL,
            SiteTitle,
            SPSiteURL
        ),
        StartRow = 0,
        Timeout = 30000,
        TrimDuplicates = True
    }
}

In the request above, we return the first 100 documents (excluding duplicates) stored in all Office 365 groups and we also retrieve some additional information such as the title of the documents (Title), the URL of the file (DefaultEncodingURL), the name of the group where it’s stored (SiteTitle) and the URL of the group (SPSiteURL).

If you want to be more precise on your search (e.g. search for documents that have a title which start with the word “Program“), then you can add new filters to your query such as the example below.

Title:Program* AND ContentClass:STS_ListItem_DocumentLibrary AND SiteTemplate:GROUP

As we have seen in this article, it’s pretty simple to search documents across all Office 365 groups and it’s just up to you to integrate and to use REST API in your different applications (mobile, Office add-ins, WebParts…).

Programmez #190 : Developing with Delve and Office 365 Video REST APIs

Interested in developing applications that use Delve and/or Office 365 Video using REST APIs ?

Take a look to my article in the latest issue of Programmez, a magazine available in French-speaking countries (France, Belgium, Switzerland, Luxemburg, Canada…).

Programmez 190