Accedere agli eventi del calendario di un utente tramite Microsoft Graph

Completato

Hai eseguito un'app ASP.NET Core e l'hai connessa a Microsoft 365. In questa unità si apprenderà come visualizzare gli eventi del calendario di un utente per la settimana successiva. Si apprenderà anche come eseguire query sugli eventi dati per un determinato periodo. Infine, verranno fornite informazioni sui concetti select e order per visualizzare le informazioni nel modo desiderato.

Decidere quali autorizzazioni sono necessarie per l'app

Tutti i dati esposti da Microsoft Graph sono protetti e l'app deve disporre delle autorizzazioni appropriate per accedervi. L'autorizzazione necessaria dipende dal tipo di informazioni a cui l'app deve accedere. Ad esempio, per accedere al calendario dell'utente, l'app deve disporre dell'autorizzazione Calendars.Read. L'elenco esatto delle autorizzazioni necessarie per ogni operazione è disponibile nel riferimento all'API di Microsoft Graph.

Se l'app carica diversi tipi di dati, gli utenti dovranno concedere più autorizzazioni necessarie per accedere a queste informazioni. Nella tua app è consigliabile richiedere solo le autorizzazioni necessarie.

Specificare le autorizzazioni necessarie

L'elenco delle autorizzazioni concesse all'app viene inserito direttamente nel token di accesso. Lo standard OAuth le definisce “ambiti". Quando l'applicazione usa MSAL per ottenere il token di accesso, deve includere un elenco di ambiti nella richiesta a Microsoft Entra ID. Ogni operazione in Microsoft Graph ha un proprio elenco di ambiti. Se il token di accesso non ne ha uno, la richiesta verrà rifiutata.

L'applicazione di esempio archivia le autorizzazioni necessarie nel file appsettings.json in una Scopes proprietà come illustrato in precedenza.

"Scopes": "user.read presence.read mailboxsettings.read calendars.read"

Il Scopes valore della proprietà viene usato dal middleware ASP.NET Core dell’app, che gestisce il recupero di un token di accesso dopo che l'utente ha eseguito correttamente l'accesso.

Middleware: Microsoft Identity Platform e Microsoft Graph

ASP.NET Core supporta middleware che possono essere usati per autenticare e autorizzare gli utenti. Può essere usato anche per recuperare un token che può essere usato per chiamare Microsoft Graph, inserire un oggetto Microsoft Graph SDK denominato GraphServiceClientnell'applicazione, creare una cache dei token e altro ancora. Il middleware è configurato in Startup.cs e gestisce le attività seguenti.

  1. Recuperare le autorizzazioni necessarie definite nella proprietà Scopes da appsettings.json.
  2. Aggiungere il supporto per l'autenticazione OpenId.
  3. Specificare che l'applicazione è un'app Web di Microsoft Identity Platform che richiede un flusso di codice di autenticazione.
  4. Aggiungere la possibilità di chiamare l’API di Microsoft Graph con autorizzazioni specifiche.
  5. Abilitare l'inserimento delle dipendenze per GraphServiceClient(un oggetto fornito da Microsoft Graph SDK che è usato per effettuare chiamate Microsoft Graph).
  6. Aggiungere una cache dei token in memoria.
  7. Richiedere a un utente autenticato di accedere all'app.
  8. Abilitare il supporto delle Razor Pages.
  9. Aggiungere pagine dell'interfaccia utente di Microsoft Identity che forniscono supporto per l'accesso e la disconnessione dell'utente.

È possibile vedere ognuno di questi passaggi nel codice seguente definiti nel metodo ConfigureServices() di Startup.cs.

// 1. Retrieve required permissions from appsettings
string[] initialScopes =
Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');


services
  // 2. Add support for OpenId authentication
  .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)

  // 3. Microsoft identity platform web app that requires an auth code flow
  .AddMicrosoftIdentityWebApp(Configuration)

  // 4. Add ability to call Microsoft Graph APIs with specific permissions
  .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)

  // 5. Enable dependency injection for GraphServiceClient
  .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))

  // 6. Add in-memory token cache
  .AddInMemoryTokenCaches();


// 7. Require an authenticated user
services.AddControllersWithViews(options =>
{
  var policy = new AuthorizationPolicyBuilder()
      .RequireAuthenticatedUser()
      .Build();
  options.Filters.Add(new AuthorizeFilter(policy));
});

services
  // 8. Add Razor Pages support
  .AddRazorPages()

  // 9. Add Microsoft Identity UI pages that provide user
  // sign-in and sign-out support
  .AddMicrosoftIdentityUI();

Dopo aver configurato il middleware necessario, l'applicazione gestirà automaticamente l'accesso dell'utente e il recupero del token di accesso. Il token di accesso potrà quindi essere usato per recuperare gli eventi del calendario di un utente, perché conterrà le autorizzazioni necessarie. Vediamo come funziona questo processo.

Recuperare degli eventi del calendario di un utente per un determinato periodo

Per ottenere gli eventi del calendario di un utente da Microsoft Graph, è necessario chiamare l'endpoint /me/calendarview . L'endpoint restituisce un elenco di eventi del calendario dal calendario predefinito dell'utente connesso. È possibile effettuare la chiamata a Microsoft Graph utilizzando l'oggetto GraphServiceClient menzionato in precedenza nella sezione sul middleware. GraphServiceClient fornisce API che è possibile usare per chiamare Microsoft Graph senza dover effettuare manualmente chiamate HTTP. Per visualizzare gli eventi del calendario per la settimana successiva, è necessario definire le date di inizio e fine settimana.

// Configure a calendar view for the current week
var startOfWeek = DateTime.Now;
var endOfWeek = startOfWeek.AddDays(7);

Queste date vengono quindi aggiunte a un elenco QueryOption che definisce l'intervallo di eventi da selezionare.

var viewOptions = new List<QueryOption>
{
  new QueryOption("startDateTime", startOfWeek.ToString("o")),
  new QueryOption("endDateTime", endOfWeek.ToString("o"))
};

Un oggetto GraphServiceClient (inserito nel costruttore della classe modello della pagina Razor) viene quindi usato per chiamare Me.CalendarView e l'elenco viewOptions viene passato al metodo Request per limitare i risultati. Il codice include anche il fuso orario preferito dell'utente, chiamando il metodo Header.

// Use the injected GraphServiceClient object to call into Me.CalendarView
var calendarEvents = await _graphServiceClient
    .Me
    .CalendarView
    .Request(viewOptions)
    .Header("Prefer", $"outlook.timezone=\"{userTimeZone}\"")

Ridurre al minimo la quantità di dati che Microsoft Graph recupera e trasferisce migliorerà significativamente le prestazioni dell'app. Il metodo Select di GraphServiceClient’s può essere usato per selezionare proprietà specifiche che verranno usate dall'app.

.Select(evt => new
{
    evt.Subject,
    evt.Organizer,
    evt.Start,
    evt.End
})

Infine, il metodo OrderBy viene usato per specificare come ordinare gli elementi risultanti e viene chiamato GetAsync per avviare la richiesta.

.OrderBy("start/DateTime")
.GetAsync();

In questo caso, il codice ordinerà i risultati in base alla proprietà secondaria della proprietà start denominata DateTime. Per ordinare in base a più campi, specificare un elenco di campi delimitati da virgole. È anche possibile specificare se si vogliono ordinare gli elementi in ordine crescente o decrescente aggiungendo la parola chiave asc o desc alla query. La versione completa del codice è illustrata di seguito:

// Configure a calendar view for the current week
var startOfWeek = DateTime.Now;
var endOfWeek = startOfWeek.AddDays(7);

var viewOptions = new List<QueryOption>
{
    new QueryOption("startDateTime", startOfWeek.ToString("o")),
    new QueryOption("endDateTime", endOfWeek.ToString("o"))
};

// Use the injected GraphServiceClient object to call into Me.CalendarView
var calendarEvents = await _graphServiceClient
    .Me
    .CalendarView
    .Request(viewOptions)
    .Header("Prefer", $"outlook.timezone=\"{userTimeZone}\"")
    .Select(evt => new
    {
        evt.Subject,
        evt.Organizer,
        evt.Start,
        evt.End
    })
    .OrderBy("start/DateTime")
    .GetAsync();

Vediamo ora come si può usare questo codice nell'applicazione.