Graph

+
~

Graph is the gateway to data and intelligence in Microsoft 265. In Microsoft 365, three main components facilitate data access and flow:

Querying with REST

Uses an OData namespace microsoft.graph. A few API sets are defined in sub-namespaces, such as call records API which are in microsoft.graph.callRecords.

It is generally safe to assume that types, methods and enumerations are part of the microsoft.graph namespace.

GET|POST|PATCH|PUT|DELETE 
https://graph.microsoft.com/{version}/{resource}?{query-parameters}

For numerated data, @odata.nextLink contains a URL for the next page.

Resources

A resource can be an entity or complex type. Unlike complex types, entities always include an id property.

REST Url always includes the resource you are interacting with, such as me, user, group, drive and site. Top level resources often also include relationships, which can be used to access more specific resources, like me/messages, me/drive etc.

You can also interact with methods in this way, for example me/sendMail to send an email.

Different resources may require different permissions to access. Writing to a resource typically requires more permissions than reading.

Query parameters

Standard OData system query options:

GET https://graph.microsoft.com/v1.0/me/messages?
	filter=emailAddress eq 'jon@contoso.com'

Querying with SDKs

The Graph SDKs container two components:

Three NuGet packages:

Creating a client

Clients are designed to be singleton.

var scopes = new[] { "User.Read" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Value from app registration
var clientId = "YOUR_CLIENT_ID";

// using Azure.Identity;
var options = new TokenCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};

// Callback function that receives the user prompt
// Prompt contains the generated device code that you must
// enter during the auth process in the browser
Func<DeviceCodeInfo, CancellationToken, Task> callback = (code, cancellation) => {
    Console.WriteLine(code.Message);
    return Task.FromResult(0);
};

// /dotnet/api/azure.identity.devicecodecredential
var deviceCodeCredential = new DeviceCodeCredential(
    callback, tenantId, clientId, options);

var graphClient = new GraphServiceClient(deviceCodeCredential, scopes);

Point read

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

var user = await graphClient.Me
    .GetAsync();

Lists

// GET https://graph.microsoft.com/v1.0/me/messages?
// $select=subject,sender&$filter=subject eq 'Hello world'
var messages = await graphClient.Me.Messages
    .GetAsync(requestConfig =>
    {
        requestConfig.QueryParameters.Select =
            ["subject", "sender"];
        requestConfig.QueryParameters.Filter =
            "subject eq 'Hello world'";
    });

Delete

// DELETE https://graph.microsoft.com/v1.0/me/messages/{message-id}
// messageId is a string containing the id property of the message
await graphClient.Me.Messages[messageId]
    .DeleteAsync();

Create

// POST https://graph.microsoft.com/v1.0/me/calendars
var calendar = new Calendar
{
    Name = "Volunteer",
};

var newCalendar = await graphClient.Me.Calendars
    .PostAsync(calendar);

Best practice