こんにちは。SharePoint サポートの森 健吾 (kenmori) です。
導入
コード付きサンドボックス ソリューションを代替のソリューションに置き換える開発を実施されている方が多いと考えております。サンドボックス ソリューションの変換先としては、以下のようなガイダンスが記載されています。
タイトル : サンドボックス ソリューションの変換ガイダンス
アドレス : https://msdn.microsoft.com/ja-jp/pnp_articles/sandbox-solution-transformation-guidance
上記ガイダンスにからリンクしていくと、以下のページにイベント レシーバーの代替としてリモート イベント レシーバーの使用が紹介されています。
タイトル : SharePoint でリモート イベント レシーバーを使用する
アドレス : https://msdn.microsoft.com/ja-jp/pnp_articles/use-remote-event-receivers-in-sharepoint
今回の投稿では、上記内容を少しわかりやすく説明することと、既存のサンドボックス ソリューションに近い形で置き換えやすいサンプルに仕上げましたので、その内容をご提案します。
なお、リモート イベント レシーバーという仕組みを使う上で運用的に重要な点が 1 点あります。リモート イベント レシーバーは SharePoint Online から直接ネットワーク接続できる場所にイベント処理用の外部 Web サイトを用意する必要があります。この時点で、Azure Web App などのクラウド ベースの Web サイトや、インターネット公開したオンプレミスの Web サイトが必要になり、構成変更追加コストが生じる点についてはあらかじめご了承ください。
リモート イベント レシーバーへの置き換えを理解するポイント
サンドボックスのイベント レシーバーをプロバイダーホスト型アドインのリモート イベント レシーバーに置き換える上で技術的なポイントが 2 点あります。
1) アプリ イベント レシーバー (AppEventReceiver.svc) エンドポイントの使用
本来、アプリ イベント レシーバー エンドポイントは、ホスト サイト (HostWeb) 上でアドインのインストール、アンインストールなどに関連するイベントを処理するためのものです。
SharePoint Online は、アプリ イベント レシーバー用のエンドポイントに対しては、ホスト サイト側のユーザー コンテキスト情報 (アクセス トークン取得のために必須) が送信できるような実装になっています。この動作を利用して、リストやアイテム イベントでも同エンドポイントを呼び出すよう実装します。
ある程度の経験者の場合、RemoteEventReceiver1.svc などがホスト サイトからコンテキスト情報を受け取れないことを知っているため、このような機能は実現できないと判断している人も多いかもしれません。アプリ イベント レシーバー エンドポイントを使用することが実現可能な根拠の 1 つです。
2) コードなしサンドボックス ソリューションの Elements.xml にて、リモート イベント レシーバー呼び出し先である Url 要素を使用
コード付きのイベント レシーバーは SharePoint Online では新規でアクティブ化できないよう制御されましたが、コードがない場合アクティブ化は可能です。Elements.xml を書き換えて、イベント レシーバーの参照を変更し、マネージ コード アセンブリから、外部エンドポイントに切り替えることが可能です。Elements.xml に外部リモート イベント レシーバー呼び出しのためのスキーマは提供されています。
実践
それでは、実際にプロバイダー ホスト型アドインを開発していきます。投稿をコンパクトにするため、プロバイダー ホスト型アドインの開発経験者が前提の記載となりますが、ご了承ください。
1. プロバイダー ホスト型アドインの追加
1-1. Visual Studio で SharePoint アドイン プロジェクトを作成し、プロバイダー ホスト型アドインを作成します。
1-2. ソリューション エクスプローラで、プロバイダー ホスト アドイン プロジェクトを選択し、プロパティ シートで “アプリのハンドルがインストールされました” を True にします。
以下のように、外部ホスト Web サイト内にアプリ イベント レシーバー エンドポイントが自動生成されます。
1-3. AppEventReceiver.svc.cs を開き、ProcessEvent にロジックを実装します。
現在のサンドボックス ソリューションの実装を CSOM 形式に変換して、ここに移植します。
(例. ここでは、条件付きでアイテム追加をキャンセルするサンプルを記載しています)
public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties) { SPRemoteEventResult result = new SPRemoteEventResult(); switch (properties.EventType) { case SPRemoteEventType.ItemAdding: HandleItemAdding(properties, result); break; } return result; } private void HandleItemAdding(SPRemoteEventProperties properties, SPRemoteEventResult result) { try { using (ClientContext clientContext = TokenHelper.CreateRemoteEventReceiverClientContext(properties)) { if (properties.ItemEventProperties.AfterProperties["Title"] != null && !properties.ItemEventProperties.AfterProperties["Title"].ToString().ToLower().StartsWith("test")) { throw new Exception("Title should start with 'TEST'."); } else { result.Status = SPRemoteEventServiceStatus.Continue; } } } catch (Exception ex) { result.Status = SPRemoteEventServiceStatus.CancelWithError; result.ErrorMessage = ex.Message; } }
1-4. プロバイダー ホスト型アドインのプロジェクト内にある AppManifest.xml にて、[アクセス許可] をクリックし、Web に FullControl など (今回のサンプルでは Read でも可) を付与します。
1-5. 外部ホスト Web サイトを公開し、プロバイダー ホスト型アドインの *.app ファイルを生成します。
一般的な展開手順 (例. Azure Web App への展開) は以下のサイトにまとめておりますので、ご参考にしてください。
タイトル : プロバイダー ホスト型アドインを Azure Web App として展開する方法
アドレス: https://blogs.technet.microsoft.com/sharepoint_support/2016/08/27/how-to-deploy-provider-hosted-addin-web-to-azure-web-app/
なお、確認のポイントとして、出来上がりの AppManifest.xml をコードで開くと以下のようになります。
2. サンドボックス ソリューション側の変更点
イベント レシーバーを実装している Elements.xml にて、Assembly や Class などのReceiver の子要素を削除し、代わりに以下のように Url 子要素を指定します。
2-1. 既存のサンドボックス ソリューションをコピーして、開きます。
2-2. Elements.xml を以下のように編集します。
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Receivers ListTemplateId="100">
<Receiver>
<Name>ItemAdding</Name>
<Type>ItemAdding</Type>
<SequenceNumber>0</SequenceNumber>
<Url>https://spremoteeventtest********.azurewebsites.net/Services/AppEventReceiver.svc</Url>
</Receiver>
</Receivers>
</Elements>
2-3. イベントレシーバーのロジック (*.cs) をすべて削除します。
2-4. サンドボックス ソリューションのプロジェクトのプロパティにて、“パッケージにアセンブリを含める” を False に指定します。
2-5. [ビルド] – [配置] をクリックして、コードなしのソリューション パッケージ (*.wsp) を生成します。
上記のように既存のサンドボックス ソリューションからコードを削除して、レシーバー URL をアドインのリモート レシーバーに指定することで、既存のソリューションを置き換えることができます。
動作確認
サンプルコードの実装通り、TEST で始まらないタイトルを持つアイテムの投稿をブロックすることができました。
まとめ
上記実装方法としては、既存のサンドボックス ソリューションの置き換えやすさを考慮した 1 つの例となります。仕組みを一から考え直す場合は、前半にて記載した 2 つのポイントのみ認識を合わせれば、色々なパターンの実装が可能と考えております。是非、ご参考にしていただき、お役立てください。