1 of 20

Microsoft Graph API

Mike Peat - Unicorn InterGlobal, UK

2 of 20

What is Microsoft Graph?

  • Essentially it is the next generation of Microsoft's 365 API
  • The term "Graph" was used because it was "sexy" at the time (just IMHO, obviously 😉)
  • Facebook had called their API "Graph", because the way their data is structured - Friends and the relationships between them - was graph-like
  • MS Graph API really has none of the "graph-like" characteristics of Facebook's: it is really just a name

3 of 20

What is Microsoft Graph?

  • MS Graph has over 250 operations listed in Graph Explorer (and many which are not!), on such areas as:
    • Microsoft Teams (11)
    • Outlook Mail (10)
    • Applications (8)
    • OneDrive (5)
    • Excel (7)
    • Identity and Access (14)
  • And many, many more

4 of 20

A bit of history

  • In late 2014 Chip got excited because Microsoft were making their Office 365 API public
  • He asked me to try to interface with it from DataFlex
  • While it turned out that talking to the API was relatively easy, getting properly authenticated access to it was not!
  • Using LoginID and Password was acceptable for development and testing, but OAUth2 was required (well, very strongly recommended) for production

5 of 20

OAuth2

  • I'm not going to get into OAuth2 here
  • I have a presentation on-line about it from the Berlin EDUC
  • However I have updated the DataFlex OAuth2 component to use JSON objects, and now have a Windows as well as a Web version (it just uses an embedded browser)
  • And it also now caters for refresh tokens and logging out

6 of 20

Microsoft 365 API

  • Back in 2015, we had fewer tools
  • Critically, we didn't have JsonObjects
  • So the only sensible way we could deal with the data - both sent and received - was through structs
  • However, although not the 250+ operations of today's Graph, the MS 365 API then had well over 60 operations
  • Each of those operations might have both input and output JSON
  • Most needed multiple layers of structs

7 of 20

Microsoft 365 API

  • To try to tame all that, I took a multi-pronged approach
  • To deal with JSON, we had Sture's library with its JsonFunctions package
  • So I wrote a program called RESTGen, which would take a sample of JSON as input, then generate the required structs to hold that JSON, each in its own pkg, which also contained the methods for moving to and from JSON strings to structs, containing - moderately byzantine - calls to Sture's code

8 of 20

Dealing with JSON - old style

Struct tO365CalEvents

String _odata_context

Procedure Construct_Object

Property String psMap__odata_context "_odata_context"

Procedure JsonToStruct tJsonNode strJson tO365Calevents ByRef strValue

String sMemberName sSimpleValue

Get psMap__odata_context to sMemberName

If (sMemberName <> "") Begin

Get ObjectMemberSimple of oJsonFunctions strJson sMemberName ;

to sSimpleValue

Get StringFromString of oSimpleTypeStringConversions sSimpleValue ;

to strValue._odata_context

End

Extracting just one scalar element of the JSON to a struct member:

9 of 20

Dealing with JSON - old style

  • There would also be a StructToJson procedure for going the other way
  • The API often uses JSON member names containing characters we couldn't use in struct member names (we also didn't have the { Name = "xxx" } meta-tag in those days), like: "@odata.context" (hint: it's the dot!)
  • So there were also routines that replaced such characters in the input JSON with "_" and did the reverse to output JSON, mapping names we couldn't deal with to those we could

10 of 20

Managing MS 365 requests

  • To avoid having masses of logic dealing with the sending of individual requests and the processing of their inputs and outputs, I had a cRestRequestBroker class which allowed individual calls to only require a few lines of code:
  • Set up the environment and the path
  • Set a few properties of the Broker object
  • Invoke the "HandleCall" of the Broker
  • Return the result (actually in a ByRef argument)

11 of 20

Code for GetEvents in MS 365

  • The API itself was made up of ~70 of these calls

Function GetEvents String sCalendarID tO365CalEvents ByRef tEvents String sParams ;

Returns Boolean

String sPath

Integer iOK

Send SetForOutlook

Get psOutlookBasePath to sPath

If (sCalendarID = "") ;

Move (sPath + "me/events") to sPath

Else ;

Move (sPath + "me/calendars/" + ;

sCalendarID + "/events") to sPath

If (sParams <> "") ;

Move (sPath + "?" + sParams) to sPath

Set phoOutputTranslator of oBroker to oStructHandler_tO365CalEvents

Set phmOutputTransProc of oBroker to (RefProc(JsonStringToStruct))

Set pbExpectOutput of oBroker to True

Get HandleCall of oBroker "GET" sPath "" (&tEvents) to iOK

Function_Return (iOK = 1)

End_Function

12 of 20

But with our new tools and now for Graph…

  • It all gets much easier! 😀
  • Because we now have JsonObjects we no longer need structs to deal with the sent and received data, and no need for Sture's JSON code
  • And because we now have the { Name = "xxx" } meta-tag we don't need to "translate" JSON member names if we do use structs
  • In addition, because we don't have to deal in either structs or strings all the time, we no longer need the cRestRequestBroker

13 of 20

So what do we need for MS Graph?

  • We still need OAuth2 to log in to the service and give us an access token to use in our calls
  • We need an HTTP component (cHttpTransferREST) to actually make the calls, so that has a MakeJsonCall function
  • That takes the arguments:
    • The VERB to use (GET, POST, etc.)
    • The Path to make the call to
    • Any query string parameters we need to pass
    • The HTTP Body to pass - if any - (which will be a JSON object)

14 of 20

So what do we need for MS Graph?

  • That MakeJsonCall function will return either a JSON object containing the response, or an error response (0), or -1 to indicate that there was no JSON response (which might well be correct)
  • In the case of an error response, the actual error will be stored in a couple of properties (piError and psError)
  • We might still want to use structs to assemble our input and interpret the resulting responses, but they are no longer required - we could work with the JSON directly

15 of 20

The same call in the Graph API

Function GetEvents String sCalendar String sParams Returns Handle

Handle hoEvents

String sPath

If (sCalendar = "") ;

Move (GraphPath(Self) + "me/events") to sPath

Else ;

Move (GraphPath(Self) + ;

"me/calendars/" + sCalendar + "/events") to sPath

Get MakeJsonCall of (phoHttp(Self)) "GET" sPath sParams "" to hoEvents

Function_Return hoEvents

End_Function

Almost Trivial!

16 of 20

Structure

Source

OAuth2

cHttpTransferREST

View(s)

MSGraphAPI

Various API functions

Get MakeJsonCall

Get OAuth2AccessToken

Function OAuth2AccessToken

Get wpsAccessToken

Call various

API functions

Login

17 of 20

DEMO

18 of 20

The Graph API is not quite the same

  • Obviously Microsoft have changed some things from the old Office 365 API
  • The base endpoint is different (but now at least there is only one - no more Outlook or Sharepoint, although there is v1.0 or beta)
  • And some (many) of the calls and data-structures have changed or expanded and there are now many more of them (remember that 250+?)
  • You really need to build again from scratch
  • Microsoft Graph "Explorer" will give you a good overview

19 of 20

So…

  • At the moment I am not planning on developing a DataFlex component to fully map onto MS Graph
  • Three reasons:
    1. It is just too big: it took quite a while to do the ~70 operations of MS 365; the ~250 operations of Graph is a tad daunting!
    2. Better tools make it a simple process to do it yourself - if you need a given operation, it is simple to write one
    3. Many aspects of the Graph API will never be of interest to DF programmers - if only I knew which, life would be easier! 😀

20 of 20

Thank you!

Are there any questions?