使用 Microsoft Graph 存取使用者的行事曆活動

已完成

您執行了 ASP.NET Core 應用程式並將其連線至 Microsoft 365。 在此單元中,您將了解如何顯示使用者未來一週的行事曆活動。 您還將了解如何査詢指定時段的資料事件。 最後,您將了解 [選取][排序] 等概念,以便以所需的方式顯示資訊。

決定您的應用程式需要的權限

Microsoft Graph 公開的所有資料都受到保護,而且您的應用程式必須獲與適當權限才能存取它。 需要的權限取決於您的應用程式需要存取的資訊類型。 例如,若要存取使用者的行事曆,您的應用程式必須擁有 Calendars.Read 權限。 Microsoft Graph API 參考中提供每項作業所需權限的確切清單。

如果您的應用程式載入不同類型的資料,使用者將必須授與其存取此資訊所需的多個權限。 建議您僅在應用程式中要求您需要的權限。

指定必要權限

授與您應用程式的權限清單會一併放入存取權杖中。 OAuth 標準將其稱為「範圍」。 當您的應用程式使用 MSAL 來取得存取權杖,它需要在對 Azure Active Directory 的要求中包含範圍清單。 Microsoft Graph 中的每個作業都有自己的範圍清單。 如果您的存取權杖沒有其中一個權杖,則要求會遭到拒絕。

如您稍早所見,範例應用程式會將必要的權限儲存在 appsettings.json 檔案的 Scopes 屬性中。

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

Scopes 屬性值是由應用程式的 ASP.NET Core 中介軟體所使用,其會處理使用者成功登入後存取權杖的擷取。

中介軟體:Microsoft 身分識別平台和 Microsoft Graph

ASP.NET Core 支援可用來驗證和授權使用者的中介軟體。 它也可以用來擷取可呼叫 Microsoft Graph 的權杖、將名為 GraphServiceClient 的 Microsoft Graph SDK 物件插入應用程式、建立權杖快取等等。 中介軟體是在 Startup.cs 中設定,並處理下列工作。

  1. appsettings.json 擷取 Scopes 屬性中定義的必要權限。
  2. 新增 OpenId 驗證的支援。
  3. 指定應用程式是需要驗證碼流程的 Microsoft 身分識別平台 Web 應用程式。
  4. 新增使用特定權限呼叫 Microsoft Graph API 的能力。
  5. 啟用 GraphServiceClient 的相依性插入 (Microsoft Graph SDK 提供的物件,用來進行 Microsoft Graph 呼叫)。
  6. 新增記憶體內部權杖快取。
  7. 需要已驗證的使用者存取應用程式。
  8. 啟用 Razor Pages 支援。
  9. 新增提供使用者登入和登出支援的 Microsoft 身分識別 UI 頁面。

您可以在下列程式碼中查看每個步驟,其會在 Startup.csConfigureServices() 方法中定義。

// 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();

一旦設定必要的中介軟體,應用程式將自動處理使用者的登入,並擷取存取權杖。 然後可以使用存取權杖來擷取使用者的使用者事件,因為它將包含必要的權限。 讓我們看看該程序如何運作。

擷取使用者指定時間的行事曆活動

若要透過 Microsoft Graph 取得使用者的行事曆活動,您需要呼叫 /me/calendarview 端點。 它會傳回已登入使用者預設行事曆中的行事曆事件清單。 您可以使用先前在中介軟體章節提到的 GraphServiceClient 物件呼叫 Microsoft Graph。 無需手動呼叫 HTTP,GraphServiceClient 即可提供可用於呼叫 Microsoft Graph 的 API。 若要顯示下週的行事曆事件,您需要定義週的開始與結束日期。

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

然後,這些日期將新增至定義要選取之事件範圍的 QueryOption 清單中。

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

接著,將使用 GraphServiceClient 物件 (插入 Razor 頁面模型類別的建構函式中) 呼叫 Me.CalendarView,並將 viewOptions 清單傳遞至 Request 方法以限制結果。 代碼還透過呼叫 Header 方法包含使用者的偏好時區為。

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

將 Microsoft Graph 所擷取和傳輸的資料量最小化,將大幅改善您應用程式的效能。 GraphServiceClient’s 選取方法可用於選取應用程式將使用的特定屬性。

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

最後,OrderBy 方法用於指定如何對結果項目進行排序,並且 GetAsync 被呼叫以啟動要求。

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

在此情況下,代碼將依 start 屬性的子屬性 DateTime 對結果進行排序。 若要依多個欄位排序,請指定以逗號分隔的欄位清單。 您也可以透過將 ascdesc 關鍵字附加至查詢,指定以遞增或遞減順序排序項目。 代碼的完整版本如下所示:

// 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();

讓我們檢查一下如何在應用程式中使用此代碼。