SharePoint webhook の参照実装のサンプル
SharePoint のパターンとプラクティス (PnP) の参照実装では、アプリケーションで SharePoint webhooks を使用する方法を示しています。 Webhooks は、非同期 web ジョブの通知処理のため、Azure Web ジョブ、Azure SQL Server、Azure ストレージのキューなど、さまざまな Microsoft Azure コンポーネントを使用したエンタープライズ準備方法で実装されます。
参照実装は、SharePoint リストの Webhook でのみ動作します。
Microsoft 365 Platform Community (PnP) YouTube チャネルでビデオを視聴して、次の手順に従うこともできます。
適用対象: Office 365 マルチテナント (MT)。
Microsoft Azure を使用して、SharePoint の webhook を実装するのに必要なさまざまなコンポーネントをホストします。
参照実装のソース コードおよび他の資料を入手する場合、次の 2 つのいずれかを選択できます。
- SharePoint プロバイダー向けのホスト型アプリケーションのバージョン
- GitHub の SharePoint 開発者サンプル リポジトリにある Office 365 Azure AD アプリケーション
参照実装の展開
アプリケーションでは、特に SharePoint リストの webhook を管理する方法を示します。 webhook プロジェクトで再利用できる webhook のサービス エンドポイントの参照実装も含まれています。
展開ガイド
- SharePoint の webhook 参照実装の展開ガイドには、SharePoint プロバイダー向けのホスト型参照実装を展開するために使用する展開の手順の一覧が示されています。
- Office 365 Azure AD アプリケーションを展開するには、SharePoint web hooks Azure AD 参照実装の展開ガイドで説明されている手順を使用します。このガイドでは、Web API 機能を webhook サービスとして使用する方法について説明しています。
- Azure Functions を使用することに関心がある場合は、この参照実装での Azure Functions の使用方法の詳細について、「Azure Functions ガイド」を参照してください。
webhook について
Webhooks は、アプリケーションを監視する必要がある SharePoint の変更についてアプリケーションに通知します。 アプリケーションで、さらに変更を定期的にポーリングする必要はありません。 webhook を使えば、変更のたびに、アプリケーションは通知を受けます (プッシュ モデル)。 webhook は、Microsoft 固有ではありません。 他のベンダー (たとえば、WordPress、GitHub、MailChimp、その他) も採用している共通の Web 標準です。
SharePoint リストへの webhook の追加
参照実装は、SharePoint リストとともに動作します。 Webhook を SharePoint リストに追加するために、POST /_api/web/lists('list-id')/subscriptions
要求を送信することにより、アプリケーションで最初に Webhook のサブスクリプションが作成されます。 要求には、次のものが含まれます。
- webhook を追加するリストを識別するためのペイロード。
- 通知を送信する webhook のサービス URL の場所。
- webhook の有効期限。
webhook の追加を SharePoint に要求した後、SharePoint は webhook サービス エンドポイントが存在することを検証します。 検証文字列をサービスのエンドポイントに送信します。 SharePoint ではサービス エンドポイントから 5 秒以内に検証文字列が返されることを想定しています。 このプロセスが失敗した場合、webhook の作成はキャンセルされます。 サービスが展開されている場合は、これは処理され、SharePoint はアプリケーションが最初に送った POST 要求についての HTTP 201 メッセージを返します。 応答のペイロードには、新しい webhook サブスクリプションの ID が含まれています。
参照実装を見ると、Webhook CRUD の全操作が、SharePoint.WebHooks.Common プロジェクトの WebHookManager クラスに統合されるのがわかります。 webhook の追加は、AddListWebHookAsync メソッドを使用して行われます。
/// <summary>
/// This method adds a webhook to a SharePoint list. Note that you need your webhook endpoint being passed into this method to be up and running and reachable from the internet
/// </summary>
/// <param name="siteUrl">Url of the site holding the list</param>
/// <param name="listId">Id of the list</param>
/// <param name="webHookEndPoint">Url of the webhook service endpoint (the one that will be called during an event)</param>
/// <param name="accessToken">Access token to authenticate against SharePoint</param>
/// <param name="validityInMonths">Optional webhook validity in months, defaults to 3 months, max is 6 months</param>
/// <returns>subscription ID of the new webhook</returns>
public async Task<SubscriptionModel> AddListWebHookAsync(string siteUrl, string listId, string webHookEndPoint, string accessToken, int validityInMonths = 3)
{
// webhook add code...
}
SharePoint を呼び出すには、認証情報を提供する必要があります。このケースでは、アクセス トークンと共に、ベアラーの認証ヘッダーを使用します。 アクセス トークンを取得するには、ExecutingWebRequest イベント ハンドラーを介してトークンを傍受してください。
ClientContext cc = null;
// Create SharePoint ClientContext object...
// Add ExecutingWebRequest event handler
cc.ExecutingWebRequest += Cc_ExecutingWebRequest;
// Capture the OAuth access token since we want to reuse that one in our REST requests
private void Cc_ExecutingWebRequest(object sender, WebRequestEventArgs e)
{
this.accessToken = e.WebRequestExecutor.RequestHeaders.Get("Authorization").Replace("Bearer ", "");
}
SharePoint による webhook サービスの呼び出し
SharePoint は、webhook のサブスクリプションを作成したリスト内で変更を検出すると、サービス エンドポイントを呼び出します。 SharePoint からペイロードを見る場合、次のプロパティが重要であることに注意してください。
プロパティ | 説明 |
---|---|
webhook サブスクリプションの ID。 webhook の有効期限を延長するなど webhook サブスクリプションを更新する場合は、この ID が必要です。 | |
変更が発生するリストの ID。 | |
対象の変更が発生したリソースを保持しているサイトのサーバー相対 URL です。 |
注:
SharePoint は、変更が発生したという通知のみを送信し、その通知には実際の変更内容は含まれていません。 つまり、変更された Web およびリストに関する情報を取得するため、同じサービス エンドポイントを使用して、複数のサイトおよびリストから Webhook イベントを処理することができます。
サービスが呼び出されたときに、ご使用のサービスが 5 秒以内に HTTP 200 メッセージで応答することが重要です。 応答時間に関しては、この記事の後半でさらに詳しく説明しますが、基本的に非同期的に通知を処理することが求められます。 この参照実装で、これを行うには Azure の Web ジョブと Azure ストレージのキューを使用します。
対象となるサービスが必要とする変更内容の取得
前の手順で、サービス エンドポイントが呼び出されましたが、SharePoint が提供するのは、変更が起こったという情報のみで、実際の変更内容は含まれていません。 変更内容を理解するには、次の図に示すように SharePoint GetChanges()
API を使用する必要があります。
SharePoint.WebHooks.Common プロジェクトの ChangeManager クラスの ProcessNotification メソッド内における GetChanges()
実装に関して詳しく知ることができます。
同じ変更を繰り返し取得しないためには、どの時点から変更したいのかを SharePoint に通知することが重要です。 これは changeToken を渡すことで実行されます。またこれは、サービス エンドポイントが最後に使用された changeToken を保持することで次回サービスのエンドポイントが呼び出されるとき使用できるようにしておく必要があるということも示しています。
変更について注意するいくつかの重要なポイントは、次のとおりです。
- SharePoint は、リアルタイムでサービスを呼び出しません。webhook のあるリストに変更が発生すると、SharePoint は webhook の呼び出しをキューに加えます。 毎分 1 回このキューを読み取り、適切なサービスのエンドポイントが呼び出されます。 この要求のバッチ処理が重要です。 たとえば、1000 件のレコードの一括アップロードが発生する場合、バッチ処理により、SharePoint がエンドポイントを 1000 回呼び出すことを防ぎます。 つまり、エンドポイントが呼び出されるのは 1 回だけですが、
GetChanges()
メソッドを呼び出す場合は、処理が必要な変更イベントが 1000 件発生することになります。 - 変更の数に関係なく、迅速な応答を保証するには、サービス エンドポイントのワークロードを非同期的に実行することが重要です。 参照実装では、Azure のパワーを活用しました。サービスでは受信ペイロードをシリアル化し、Azure のストレージ キューに保存する一方で、Azure Web ジョブが継続的に実行され、キュー内のメッセージをチェックします。 キューにメッセージがある場合、Web ジョブはそれらを処理し、非同期的にロジックを実行します。
完全なエンド ツー エンドのフロー
次の図では、完全なエンド ツー エンドの webhook フローについて説明します。
- アプリケーションでは、webhook サブスクリプションが作成されます。 そのとき、webhook を作成したリストから現在の changeToken を取得します。
- アプリケーションは、この場合 SQL Azure などの固定記憶域内の changeToken を保持します。
- SharePoint で変更が発生すると、SharePoint は、サービス エンドポイントを呼び出します。
- サービス エンドポイントでは、通知要求をシリアル化し、ストレージのキューに保存します。
- Web ジョブは、キュー内のメッセージを確認し、メッセージ処理ロジックを開始します。
- メッセージ処理ロジックでは、固定ストレージから最後に使用された変更トークンを取得します。
- メッセージ処理ロジックは、
GetChanges()
API を使用して変更点を確認します。 - 返された変更が処理されると、アプリケーションは変更に基づいて必要なことを行います。
- 最後に、アプリケーションが最後に取得した changeToken を保持するので、次回既に処理されている変更を受け取ることはありません。
webhook 更新の操作
webhook サブスクリプションは、作成時に既定値では 6 か月後、または指定した日付に期限切れとなるよう設定されています。 多くの場合、より長い時間使用できる webhook が求められます。 以下のセクションで示すパターンは、webhook サブスクリプションの有効期間を増やすのに適しています。 最初のパターンは軽量ですが、2 つ目のパターンはやや複雑で、別の Web ジョブをホストする必要があります。
基本的なモデル
サービスが通知を受け取るときに、サブスクリプションの有効期間に関する情報も取得します。 サブスクリプションの有効期限が切れようとしている場合は、通知処理ロジック内でサブスクリプションの有効期間を延長するだけです。 このモデルは、この参照実装で実装され、ほとんどの場合は正しく機能します。 ただし、webhook サブスクリプションを作成したリスト上に 6 か月間何も変更がない場合は、webhook サブスクリプションは延長されないまま、削除されます。
複雑だが、信頼性の高いモデル
週単位で固定ストレージからすべてのサブスクリプション ID を読み込む Web ジョブを作成します。 毎回 1 つずつ検索されたサブスクリプションを延長します。
注:
この Web ジョブは、この参照実装の一部ではありません。
SharePoint リストの webhook の実際の更新は、PATCH /_api/web/lists('list-id')/subscriptions(‘subscriptionID’)
の REST 呼び出しを使用して行うことができます。
参照実装で、webhook の更新は SharePoint.WebHooks.Common プロジェクトの WebHookManager クラスで実装されます。
webhook の更新は、UpdateListWebHookAsync メソッドを使用して行われます。
/// <summary>
/// Updates the expiration datetime (and notification URL) of an existing SharePoint list webhook
/// </summary>
/// <param name="siteUrl">Url of the site holding the list</param>
/// <param name="listId">Id of the list</param>
/// <param name="subscriptionId">Id of the webhook subscription that we need to update</param>
/// <param name="webHookEndPoint">Url of the webhook service endpoint (the one that will be called during an event)</param>
/// <param name="expirationDateTime">New webhook expiration date</param>
/// <param name="accessToken">Access token to authenticate against SharePoint</param>
/// <returns>true if successful, exception in case something went wrong</returns>
public async Task<bool> UpdateListWebHookAsync(string siteUrl, string listId, string subscriptionId, string webHookEndPoint, DateTime expirationDateTime, string accessToken)
{
// webhook update code...
}
webhook のデバッグ
SharePoint は Webhook サービス エンドポイントを呼び出すため、エンドポイントは SharePoint によって到達可能である必要があります。 これにより、開発およびデバッグがやや複雑となります。 作業を簡単にするのに使用できるいくつかの方法を次に示します。
- 初期の開発時に、独自にシリアル化したペイロードをサービスの処理ロジックに提供します。 これにより、サービス エンドポイントを展開することなく (webhook を構成することもなく)、処理ロジックを完全にテストすることができます。
- Azure のリソースへのアクセスがあれば、デバッグ ビルドを使用して、Azure App Service のデバッグを構成することによって、Azure にエンドポイントを配置ことができます。 これにより、リモートのブレークポイントを設定し、Visual Studio を使用してリモート デバッグを実行することができます。
- 開発中にサービスを展開したくない場合は、サービスの安全なトンネルを使用する必要があります。 これにより、通知サービスが共有のパブリック エンドポイントにあることを SharePoint に通知することになります。 クライアントで、その共有のパブリック サービスに接続するコンポーネントをインストールすると、いつパブリック エンドポイントへの呼び出しが行われてもクライアント コンポーネントが通知を受け、ローカル ホストで実行されているサービスにペイロードをプッシュします。 ngrok は、このように webhook サービスをローカルでデバッグするのに使用できる安全なトンネル ツールの実装の 1 つです。