SharePoint アドインの更新イベントのハンドラーを作成する
作業の開始前に、「アドイン イベントを処理する」と「SharePoint アドインを更新する」、そこに示されている前提条件と主要な概念を十分に理解している必要があります。
注意
バージョン番号付けシステム: 一貫性を保つため、このトピックではアドインのバージョン番号は 1.0.0.0、2.0.0.0、3.0.0.0 などであるものとします。ただし、ロジックとガイダンスは、番号付けシステムに関係なく適用されます。
UpgradedEventEndpoint レシーバーを作成する
カスタムの更新ロジックの場合は、アドイン更新イベントを処理する SharePoint リモート イベント レシーバーを作成できます。 この技法は注意深く使用してください。 別の方法では実行できない更新手順にのみ使用してください。 また、「アドイン イベントを処理する」に記載されたガイダンスは、アドイン インストール イベントおよびアドイン アンインストール イベントと同じようにアドイン更新イベントにも当てはまります。 ガイダンスには、以下の点も含まれます。
ハンドラーは、30 秒以内に完了してキャンセルまたは続行のステータスを SharePoint に返す必要があります。 それ以外の場合、SharePoint はハンドラーを再度呼び出します。
ハンドラーがキャンセル ステータスを返すと、SharePoint は 3 回まで再試行を実行します。
通常は、ハンドラーにロールバックと「既に実行」ロジックを含める必要があります。
**UpgradedEventEndpoint** ハンドラーが役に立つシナリオの 1 つに、計算フィールドをリモート データベースに追加する場合があります。City 列を追加し、その値は既に存在する Postal Code 列から計算されるものと仮定します。 **UpgradedEventEndpoint** ハンドラーのコードでは、データベースの既存の項目を反復処理し、Postal Code フィールドの値と、郵便番号を都市にマップする外部データ ソースに基づいて、新しい City フィールドの値を設定できます。データベース スキーマ自体に対する変更は、データベース プラットフォームのベスト プラクティスを使用して、 **UpgradedEventEndpoint** ハンドラーの外側で行うのが最善です。
アドイン イベント用ハンドラーの作成方法の詳細については、「SharePoint アドインのイベントを処理する」と「SharePoint アドインでアドイン イベント レシーバーを作成する」を参照してください。
次に示す手順は、Visual Studio の SharePoint アドイン プロジェクトに、アドイン イベント レシーバー アイテムを追加していると仮定しています。
初めてアドイン更新イベントを処理するには
AppEventReceiver.svc.cs ファイルを開いて、ハンドラーを呼び出したイベントが更新イベントかどうかをテストする条件構造を ProcessEvent メソッドに追加します。 この構造の内側に更新コードを追加します。 コードで SharePoint にアクセスする必要がある場合は、SharePoint マネージ コード クライアント オブジェクト モデル (CSOM) または Representational State Transfer (REST) インターフェイスを使用できます。
メソッド内での条件構造の場所は、メソッドの他のコードがどのように構造化されているかにより異なります。 通常は、アドインのインストール イベントとアンインストール イベントをテストするのと似た条件構造になります。 ProcessEvent に渡される SPRemoteEventProperties オブジェクトの特定のプロパティまたはサブプロパティで null 値または他の無効な値をテストする条件構造の内部になる場合があります。 また、 try ブロックの中になることもあります。
構造の例を次に示します。 properties オブジェクトは SPRemoteEventProperties オブジェクトです。
if (properties.EventType == SPRemoteEventType.AppUpgraded) { }
ハンドラー内で CSOM を使用するには、 TokenHelper.CreateAppEventClientContext メソッドを呼び出して ClientContext オブジェクトを取得する using ブロックを (条件ブロックの中に) 追加します。 アドイン Web にアクセスするには、2 番目のパラメーターに true を指定します。 ホスト Web にアクセスする場合は、false を指定します。 両方にアクセスする必要がある場合は、2 つの異なるクライアント コンテキスト オブジェクトが必要になります。
ハンドラーで SharePoint 以外のコンポーネントにアクセスする必要がある場合は、そのコードをクライアント コンテキスト ブロックの外側に配置します。コードは次のような構造になります。
if (properties.EventType == SPRemoteEventType.AppUpgraded) { using (ClientContext cc = TokenHelper.CreateAppEventClientContext(properties, true)) { // CSOM code that accesses the add-in web } using (ClientContext cc = TokenHelper.CreateAppEventClientContext(properties, false)) { // CSOM code that accesses the host web } // Other update code }
REST インターフェイスを使用するには、コードで TokenHelper クラスの他のメソッドを使用してアクセス トークンを取得します。その後、SharePoint に対して行う要求にこのトークンを組み込みます。詳細については、「 SharePoint REST エンドポイントを使用して基本的な操作を完了する」を参照してください。コードは次のような構造になります。
if (properties.EventType == SPRemoteEventType.AppUpgraded) { string contextTokenString = TokenHelper.GetContextTokenFromRequest(Request); if (contextTokenString != null) { contextToken = TokenHelper.ReadAndValidateContextToken(contextTokenString, Request.Url.Authority); accessToken = TokenHelper.GetAccessToken(contextToken, sharepointUrl.Authority) .AccessToken; // REST code that accesses SharePoint } // Other update code }
SharePoint にアクセスするには、REST コードでホスト Web またはアドイン Web (またはその両方) の URL がわかっていることも必要になります。 これらの URL は、どちらも ProcessEvent メソッドに渡される SPRemoteEventProperties オブジェクトのサブプロパティです。 次のコードは、それらの取得方法を示しています。
Uri hostWebURL = properties.AppEventProperties.HostWebFullUrl; Uri appWebURL = properties.AppEventProperties.AppWebFullUrl;
アドインの 2 回目 (または 3 回目以降) の更新を行う場合、一部の更新ロジックが同じアドイン インスタンスに対して複数回実行されないようにすることが必要な場合があります。以下の手順ではその方法を示します。
2 回目以降の更新でのアドイン更新イベントを処理するには
AppEventReceiver.svc.cs ファイルを開いて、1 回目の更新 (1.0.0.0 から 2.0.0.0) での更新アクションを実装したコードを探します。 これを、以前の更新コードと呼ぶことにします (このコードは、通常、クライアント コンテキストまたはアクセス トークンを取得する承認コードの後にあります)。今回は 2 回目の更新 (2.0.0.0 から 3.0.0.0) を実行します。通常、以前の更新コードの中には、同じアドイン インスタンスに対して 2 回以上実行されないようにする必要があっても、2.0.0.0 に更新されていないアドイン インスタンスには実行する必要がある操作が存在します (この場合、インスタンスは 1.0.0.0 から 3.0.0.0 に更新されます)。
以前の更新コードは、以前のバージョンのアドイン インスタンスを調べる条件構造でラップして、このアドイン インスタンスに対してまだ実行されていない場合にのみ構造内のコードを実行します。 以前のバージョンのインスタンスは、SPRemoteEventProperties オブジェクトの PreviousVersion サブプロパティに格納されています。
この構造に、新しい更新ロジック (2.0.0.0 から 3.0.0.0 への更新用) を追加します。 次に例を示します。
Version ver2OOO = new Version("2.0.0.0"); if (properties.AppEventProperties.PreviousVersion < ver2OOO) { // Code to update from 1.0.0.0 to 2.0.0.0 (previous update code) is here. } // Code to update from 2.0.0.0 to 3.0.0.0 is here.
以降の更新ごとに、上記の手順を繰り返します。3.0.0.0 から 4.0.0.0 への更新の場合、コードは次のような構造になります。
Version ver2OOO = new Version("2.0.0.0"); if (properties.AppEventProperties.PreviousVersion < ver2OOO) { // Code to update from 1.0.0.0 to 2.0.0.0 is here. } Version ver3OOO = new Version("3.0.0.0"); if (properties.AppEventProperties.PreviousVersion < ver3OOO) { // Code to update from 2.0.0.0 to 3.0.0.0 (previous update code) is here. } // Code to update from 3.0.0.0 to 4.0.0.0 is here.
重要
UpgradedEventEndpoint ハンドラーでアドインにコンポーネントを追加する場合、そのコンポーネントは新規インストールでもアドインに含める必要があるため、同じコードを InstalledEventEndpoint ハンドラーにも追加してください。 さらに、コンポーネントを削除するための、アドインの UninstallingEventEndpoint を追加する (または修正する) 必要もあります。
For the most part, anything that was added or changed by the InstalledEventEndpoint should be reversed or deleted by the UninstallingEventEndpoint. One exception is that data that will remain useful after the add-in is removed from the second-stage recycle bin should not be deleted. (アドインで作成されるアドイン Web 以外の Web サイトはデータとみなす必要があります)。
ハンドラーにロールバック ロジックを追加する
アドインの更新中にエラーが発生した場合、SharePoint インフラストラクチャは更新プロセスを停止して、アドイン インスタンスとそのすべてのコンポーネントを以前のバージョンのアドイン インスタンスにロールバックします。 ただし、インフラストラクチャからは UpgradedEventEndpoint ハンドラーのロジックの動作内容を知る方法がないため、元に戻す操作ができないことがあります。 UpgradedEventEndpoint ハンドラーの実行中にスローされた未処理の例外は、ほぼ確実に、アドイン更新プロセス全体のロールバックが必要なことを示しますが、インフラストラクチャには UpgradedEventEndpoint のコードで実行された内容を元に戻す方法がわからないためロールバックされません。 そのため、UpgradedEventEndpoint のコードでは、次の操作が必要になります。
すべての例外をキャッチします。
カスタムのロールバック コードに分岐して、その時点までに実行された内容を元に戻します。
アドイン更新全体をロールバックする必要があることを、SharePoint インフラストラクチャに通知します。
エラー メッセージをインフラストラクチャに渡します。
UpgradedEventEndpoint が行うすべてのことを、ハンドラーの内部で明示的に元に戻す必要はありません。 アドイン Web はインフラストラクチャによってロールバックされるため、アドイン Web に対する変更をコードで元に戻す必要はありません。 ただし、一般にホスト Web または SharePoint アドインの外部にある他のコンポーネントに対して実行された変更は、UpgradedEventEndpoint ハンドラーで元に戻す必要があります。
2 回目以降の更新の場合、例外ハンドラーのロジックでは、更新されているアドイン インスタンスが必ずしもすぐ前のバージョンではないことを考慮する必要があります。すぐ前のバージョンではない場合は、更新コードの複数のブロックを元に戻すことが必要になる場合があります。このため、前のバージョンの番号に基づく条件ロジックが必要です。次に示すのは、バージョン 4.0.0.0 への更新に対するロールバック ロジックの例です。
catch (Exception e)
{
// Rollback of the 3.0.0.0 to 4.0.0.0 update logic goes here.
Version ver3OOO = new Version("3.0.0.0");
if (properties.AppEventProperties.PreviousVersion < ver3OOO)
{
// Rollback of the 2.0.0.0 to 3.0.0.0 update logic goes here.
}
Version ver2OOO = new Version("2.0.0.0");
if (properties.AppEventProperties.PreviousVersion < ver2OOO)
{
// Rollback of the 1.0.0.0 to 2.0.0.0 update logic goes here.
}
}
最後に、エラー処理では SPRemoteEventResult オブジェクトにエラー メッセージとキャンセル ステータスを割り当てる必要があります。このオブジェクトは、ProcessEvent メソッドで SharePoint 更新インフラストラクチャに返します。 次に例を示します。 このコードの場合、result は ProcessEvent メソッドで既に宣言されている SPRemoteEventResult オブジェクトです。
catch (Exception e)
{
result.ErrorMessage = "custom message " + e.Message;
result.Status = SPRemoteEventServiceStatus.CancelWithError;
// Rollback logic from the preceding code snippet is here.
}
重要
SPRemoteEventServiceStatus.CancelWithError (または SPRemoteEventServiceStatus.CancelNoError) を Status プロパティに割り当てることが重要です。 このプロパティによって、更新をロールバックするようにインフラストラクチャに通知します。 ただし、SharePoint は更新のロールバックを行う前に 3 回ハンドラーを試行します。
ハンドラー委任戦略を使用する
ハンドラー委任戦略 (「アドイン イベントを処理する」を参照) は、UpdatedEventHandler でも使用できます。 ロールバックと「既に完了」ロジックがバンドルされてリモート コンポーネントで実行されるだけでなく、バージョン管理ロジックもバンドルされて実行されます。 ここにも、通常は複数のリモート システムの更新には使用できないという、この戦略の制限が当てはまります。
次の手順
「アドイン更新の主要な手順」に戻るか、次のいずれかの記事に直接移動して、SharePoint アドインの次の主要なコンポーネントを更新する方法を参照してください。
- SharePoint のアドイン Web コンポーネントを更新する
- SharePoint のホスト Web コンポーネントを更新する
- SharePoint アドインのリモート コンポーネントを更新する