Microsoft GraphはREST APIで構成されていますが、C#などの.NET環境から扱うためのSDKも用意されています。ここでは.NET用のSDKであるMicrosoft Graph .NET Client Libraryの概要と基本的な使い方を説明します。
[toc]Microsoft Graph .NET Client Libraryについて
Microsoft Graph .NET Client LibraryはMicrosoft Graphの.NET環境によるラッパーで、以下のライブラリから構成されています。
通常用いられるのはMicrosoft.Graphですが、Microsoft.Graph.Betaにはベータ機能が含まれています。また、Microsoft.Graph.AuthはMicrosoft Authentication Libraryのラッパーで、Microsoft Graphのユーザー認証に関するライブラリが含まれています。ただし、Microsoft.Graph.Authはまだプレリリース段階となっているので注意してください。
Microsoft GraphのSDKについては以下もご覧ください。
Microsoft Graphの認証方法
Microsoft Graphによる認証ライブラリのラッパーも作成されているようですがまだプリリリース段階であり、現状ではMicrosoft Authentication Library (Microsoft.Identity.Client 名前空間)が用いられています。
実際の認証方法については以下の記事をご覧ください。
Microsoft Graph .NET Client LibraryにおけるMicrosoft GraphへのリクエストはGraphServiceClientクラスのインスタンスを起点に作成するので、まずはユーザー認証を行ってGraphServiceClientインスタンスを取得しましょう。
Microsoft Graph リクエストの作成
リクエスト構築方法の概要
GraphServiceClientインスタンスを起点にRequestBuilderをつなげていって、最後にRequestメソッドでリクエストを完成させ、GetAsync / CreateAsync / UpdateAsync / DeleteAsyncメソッドなど実際の処理に合わせたメソッドでそれを実行します。なお、Microsoft Graph .NET Client LibraryはMicrosoft GraphのREST APIのラッパーなので、このリクエストの組み立て方は基本的にREST APIにおけるHTTPメソッドのURLに準拠したものになっています。
それではREST APIのHTTPメソッドとMicrosoft Graph .NET Client LibraryにおけるC#の処理とをいくつか比較してみていきましょう。
例:自分の予定表を一覧表示する
REST API
GET /me/calendars
C#
await graphClient.Me.Calendars.Request().GetAsync();
- graphClient:GraphServiceClientインスタンス
例:自分のカレンダーの指定したイベントを削除する
REST API
DELETE /me/calendars/{id}/events/{id}
C#
await graphClient.Me.Calendars[calendarId].Events[eventId].Request().DeleteAsync();
- graphClient:GraphServiceClientインスタンス
- calendarId:カレンダーID
- eventId:イベントID
このようにGraphServiceClientインスタンスに続けてREST APIにおけるHTTPメソッドのURLに準じてプロパティ/メソッドを続けてRequestBuilderを構築していき、最後にRequestメソッドでリクエストを完成させてそれを実行します。
2つ目の例のカレンダーイベントの削除の処理をC#の文法的な側面から説明してみましょう。GraphServiceClientクラスには各種のRequestBuilderインターフェイスを実装したプロパティが用意されていて、そのうちの1つがMeプロパティなので今回はそれを選択しています(もちろん自分以外のユーザーのカレンダーなどにアクセスする場合はUsersプロパティを選択することになります)。このMeプロパティはIUserRequestBuilderインターフェイスを実装しており、そこにはカレンダーやコンタクト、メールなど操作可能な様々なものが用意されています。今回はまずイベントの操作をするカレンダーを選ぶ必要があるので、Calendarsプロパティを選択します。これはインデクサが使えるので、[ ]でカレンダーIDを指定することでICalendarRequestBuilderインターフェイスを実装したオブジェクトが得られます。そのEventsプロパティを選択し、またインデクサでイベントIDを指定することでIEventRequestBuilderインターフェイスを実装したオブジェクトが得られます。これで削除したいイベントを指定できたので、最後に得られたオブジェクトのRequestメソッドでリクエストを完成させ、DeleteAsyncメソッドでそのイベントを削除します。
RequestBuilderの規則
RequestBuilderの種類はリクエストの数だけ存在して非常に複雑ですが、ある程度の規則性を持っているのでまずはそれを理解していきましょう。ここではその規則について説明していきます。
RequestBuilderのプロパティ/メソッドもまたRequestBuilder
RequestBuilderのプロパティ/メソッドもまたRequestBuilderになっているので、RequestBuilderをつなげていってリクエストを構築することが可能になります。このようにメソッドやプロパティをつなげていくスタイル(メソッド・チェーン)をプログラミング用語でFluentインターフェイスといいます。
「****CollectionRequestBuilder」はインデクサでアイテムを指定できる
名称が「****CollectionRequestBuilder」となっていてCollectionが入るRequestBuilderはインデクサでその要素を選択することが可能です。
例えば、カレンダーの中に含まれるイベントのコレクションであるICalendarEventsCollectionRequestBuilderの場合は、インデクサでイベントIDを指定することで個々のイベントを表すIEventRequestBuilderを取得できます。
RequestBuilderの役割は与えられた要素をつなぎ合わせてREST APIのURLを構築しているだけ
RequestBuilderがやっていることは結局REST APIにおけるHTTPメソッドのURLを構築していっているだけなので、Microsoft Graph .NET Client Libraryを使ってリクエストを送っても最終的には内部的にREST APIのHTTPメソッドに変換されて処理されます。そうは言っても、C#の文法に則ってリクエストをコーディングできるのでMicrosoft Graph .NET Client Libraryを用いることでプログラミングは格段にやりやすくなるという利点があります。また、RequestBuilderの順番にURLをつなぎ合わせるので、RequestBuilderがREST APIにおけるHTTPメソッドのURLの順番と同じになるのは当然のことと言えます。
なお、RequestBuilderが構築したHTTPメソッドのURLはRequestUrlプロパティで確認可能です。
RequestBuilderは必ずRequestメソッドを持っている
RequestBuilderは必ずRequestメソッドを持っているので、リクエストの構築が終わったら一番最後のRequestBuilderのRequestメソッドを呼び出すことでリクエストを完成させることができます。このRequestメソッドはオーバーロードされていて、引数を取らないものとOption型でオプションを引数として指定するものの2つがあるので、REST APIでオプションのクエリパラメーターを指定する必要があるときはこのRequestメソッドの引数に指定します。
例えば、IUserRequestBuilderの場合はRequestメソッドを実行することでIUserRequestを生成することができます。
リクエストに対する操作
リクエストにはそれぞれ実行可能なHTTPメソッドに対応するメソッド(GetAsync / CreateAsync / UpdateAsync / DeleteAsyncメソッドなど)が用意されているので、これを実行することでリクエストを実行できます。また、取得する情報を絞り込んだり関連エンティティーも一緒に取得するようにしたりと、リクエストを修飾するためのメソッドも用意されています。
情報を絞り込んで取得する
Selectメソッドを用いることで取得する情報の項目を絞り込むことができます。
例えばユーザー情報を表すUserクラスには様々な情報が含まれますが、表示名だけ欲しい場合はそのほかの項目は不要です。そのような場合は、表示名(DisplayNameプロパティ)だけに絞り込んで取得するように指定することでダウンロード時間を短縮するとともにデータ通信量も抑えることができます。
条件に一致するエンティティーのみを取得する
Filterメソッドを用いることでエンティティーのリストの中から条件に合うエンティティーのみを抽出して取得することができます。
エンティティーの一覧をソートして取得する
OrderByメソッドを用いることでエンティティーのリストの順番を指定された項目をもとに並び替えて取得することができます。OrderByメソッドの引数には取得したエンティティーのプロパティうち、どの項目で並べ替えたいかを指定します。ここで、この項目は文字列型などの基本型である必要があります。
例えば、カレンダーのイベントをイベント名で並べ替えて取得する際は次のようにします。
await graphClient.Me.Calendar.CalendarView.Request(options).OrderBy("Subject").GetAsync();
ここではEventクラスのSubjectプロパティをOrderByメソッドの引数に文字列として指定しています。
では、イベントの開始日で並べ替えるにはどうしたらよいでしょうか?開始日はEventクラスのStartプロパティで指定されますが、これはDateTimeTimeZone型のプロパティなのでこのままではOrderByメソッドの引数に指定できません。実際の日付を表すのはDateTimeTimeZone型のDateTimeプロパティなので、OrderByメソッドの引数に指定するのはStartプロパティで得られるDateTimeTimeZone型のオブジェクトのDateTimeプロパティとなります。REST APIがベースとなっているので、階層構造は「/(スラッシュ)」でつなげる必要があり、「Start/DateTime」となります。
await graphClient.Me.Calendar.CalendarView.Request(options).OrderBy("Start/DateTime").GetAsync();
関連するエンティティーも取得する
Expandメソッドを用いることで、要求しているエンティティーに関連するエンティティーも同時に取得することができます。
Microsoft Graph SDKの使い方については以下のサイトもご覧ください。
エンティティーのページ化されたコレクションの扱い方
Microsoft Graphでクラウド上から多数のエンティティーのリストを取得する場合は、一気に大量のデータをダウンロードしてしまうとパフォーマンスの問題が出てきたり、サーバーに負荷がかかったりする可能性があります。そのため、エンティティーのコレクションはページと呼ばれる塊に分割されて1つ1つページごとにダウンロードしていくという流れになります。コレクションページはICollectionPage<T>インターフェイスを実装して定義されています。
コレクションページにまだ続きがある場合は、そのページに次のページへのリンクが格納されます。このコレクションページを操作するための仕組みがPageIteratorクラスに用意されており、IterateAsyncメソッドを用いることで複数のページに対して反復的に処理を実行して、複数ページにまたがる全てのコレクションを取得できるようになります。
以下のコード例ではデフォルトカレンダーから2021/1/1-2021-5/1のイベントをすべて取得するコードを示しています。
コード例
//ユーザー認証 (https://biotech-lab.org/articles/9029 参照)
GraphServiceClient graphClient = await AuthenticationHelper.GetAuthenticatedClientAsync();
//リクエストのオプションを作成
var options = new List<QueryOption>();
options.Add(new QueryOption("StartDateTime", "2021-01-01T10:00:00.0000000"));
options.Add(new QueryOption("EndDateTime", "2021-05-01T10:00:00.0000000"));
//イベントのコレクションページを取得
var events = await graphClient.Me.Calendar.CalendarView.Request(options).OrderBy("start/DateTime").GetAsync();
//すべてのページのイベントを保持するリストを作成
List<Event> event_List = new List<Event>();
//PageIteratorを初期化
var pageIterator = PageIterator<Event>.CreatePageIterator(graphClient, events, m =>
{
event_List.Add(m);
return true;
});
//コレクションページに対する反復処理の実行
await pageIterator.IterateAsync();
16-20行目でPageIteratorクラスのインスタンスを作成し、23行目でIterateAsyncを実行しています。これによりevent_Listですべてのイベントがリストとして得られます。
コレクションページの扱い方については以下のサイトもご覧ください。
コメント