プロバイダー向けのホスト型アドインに SharePoint の書き込み操作を追加する
これは、プロバイダー ホスト型の SharePoint アドインの開発の基本に関する記事のシリーズの 5 番目です。SharePoint アドイン とこのシリーズの前の記事 (プロバイダー ホスト型の SharePoint アドインの作成を始めるにある記事) をよく理解しておいてください。
注:
プロバイダー ホスト型アドインに関するこのシリーズに沿って作業してきた場合は、このトピックでも引き続き使用できる Visual Studio ソリューションを既に所有しています。 また、SharePoint_Provider-hosted_Add-Ins_Tutorials でリポジトリをダウンロードして BeforeSharePointWriteOps.sln ファイルを開くこともできます。
この記事ではコーディングに戻り、チェーンストアの SharePoint アドインに、いくつかのデータを書き込む機能を追加します。
SharePoint リスト アイテムで列の値を変更する
アドインには、香港ストアの [ローカル従業員] のリストから、企業のデータベースに従業員を追加するカスタムのリボン ボタンがあります。 ただし、ユーザーは忘れずに [会社の DB に追加済み] フィールドの値を [はい] に手動で変更する必要があります。 それを自動的に実行するコードを追加しましょう。
注:
Visual Studio のスタートアップ プロジェクトの設定は、ソリューションが開かれるたびに、既定値に戻される傾向があります。 このシリーズ記事のサンプル ソリューションを再開した直後は、次の手順を必ず実行してください。
- ソリューション エクスプローラーの上部にあるソリューション ノードを右クリックして、[スタートアップ プロジェクトの設定] を選択します。
- 3 つすべてのプロジェクトが [アクション] 列で [開始] に設定されていることを確認します。
ソリューション エクスプローラーで、EmployeeAdder.aspx.cs ファイルを開きます。
Page_Load メソッドの
AddLocalEmployeeToCorpDB
の呼び出しとResponse.Redirect
の呼び出しの間に次の行を追加します。 SetLocalEmployeeSyncStatus メソッドは、この次の手順で作成します。// Write to SharePoint SetLocalEmployeeSyncStatus();
EmployeeAdder
クラスに、次の新しいメソッドを追加します。private void SetLocalEmployeeSyncStatus() { using (var clientContext = spContext.CreateUserClientContextForSPHost()) { List localEmployeesList = clientContext.Web.Lists.GetByTitle("Local Employees"); ListItem selectedLocalEmployee = localEmployeesList.GetItemById(listItemID); selectedLocalEmployee["Added_x0020_to_x0020_Corporate_x"] = true; selectedLocalEmployee.Update(); clientContext.ExecuteQuery(); } }
このコードについては、次の点に注意してください。
- [ Added to Corporate DB (会社の DB に追加済み)] フィールドの内部名の見た目が不適切です。 内部フィールドにはスペースを含めることはできないため、ユーザーが表示名でスペースを使用してフィールドを作成すると、内部名に設定されたときに SharePoint が各スペースを 文字列 "x0020" に置き換えます。 これにより、[Added to Corporate DB] は [Added_x0020_to_x0020_Corporate_x0020_DB] になります。 内部名は 32 文字を超えることができないため、名前は "Added_x0020_to_x0020_Corporate_x" に切り捨てられます。
- [企業 DB に追加済み] 列は SharePoint UI でははい/いいえフィールドと呼ばれますが、実際にはブール値なので、値ははいではなく true に設定されます。
- ListItem クラスの Update メソッドを呼び出して、変更を SharePoint のコンテンツ データベースにコミットする必要があります。 あまり一般的ではありませんが、ここでの全般的な規則として、SharePoint データベースに保存されるオブジェクトのプロパティ値を変更する場合、オブジェクトの Update メソッドを呼び出す必要があります。
ホスト Web リストに書き込むためのアクセス許可を要求する
アドインはリストに対する読み取りだけでなく書き込み操作も実行するようになったため、アドインが要求するアクセス許可を「読み取り」から「書き込み」に昇格する必要があります。 次の手順を実行します。
- ソリューション エクスプローラーで、ChainStore プロジェクトの AppManifest.xml ファイルを開きます。
- [アクセス許可] タブを開いて、[アクセス許可] フィールドのドロップダウンから [書き込み] を選択します。
- ファイルを保存します。
アドインを実行してボタンをテストする
F5 キーを使用して、アドインを展開して実行します。 Visual Studio は、IIS Express でリモート Web アプリケーションをホストして、SQL Express で SQL データベースをホストします。 また、テスト用 SharePoint サイトにアドインを一時的にインストールして、すぐにアドインを実行します。 開始ページが表示される前に、アドインへのアクセス許可を付与するように求めるダイアログが表示されます。
アクセス許可のフォームで、リストから [現地の従業員] を選択して、[信頼する] をクリックします。
アドインの開始ページが開いたら、上部のクロム コントロールにある [サイトに戻る] をクリックします。
Web サイトのホーム ページから、[サイト コンテンツ]>[現地の従業員] に移動します。 リスト ビュー ページが開きます。
[企業 DB に追加済み] 列が [いいえ] に設定された従業員がリスト内に存在しない場合は、従業員をリストに追加しますが、[企業 DB に追加済み] チェック ボックスはオンにしないでください。
リボンで、[アイテム] タブを開きます。このタブの [アクション] セクションに、カスタム ボタン [企業 DB への追加 (Add to Corporate DB)] があります。
[企業 DB に追加済み] 列が [いいえ] の従業員をリストで選択します。
[企業 DB への追加] ボタンをクリックします (先にアイテムを選択しておく必要があります)。
EmployeeAdder ページの Page_Load メソッドがそのページにリダイレクトするため、再読み込みされているように見えます。 従業員の [企業 DB に追加済み] フィールドが、[はい] に変更されます。
注:
リストと企業のデータベースの不整合が発生するため、ユーザーが [会社の DB に追加済み] の値を手動で変更できないようにするのは何でしょうか? 今のところ何もその処理を行っていません。 この問題の解決策は、このシリーズの後の記事で説明します。
デバッグ セッションを終了 1.To、ブラウザー ウィンドウを閉じるか、Visual Studio でデバッグを停止します。 F5 キーを押すたびに、Visual Studio によって、以前のバージョンのアドインが取り消され、最新のバージョンがインストールされます。 1.ソリューション エクスプローラーでプロジェクトを右クリックし、[取り消し] を選択します。
ホスト Web サイトで新しいカスタム リストを作成する
チェーン ストア アドインの次の改善点は、既存のアイテムのフィールドを単に変更する代わりに、リストに新しいアイテムが作成されるようにすることです。 具体的には、企業レベルで新しい注文が発注されたときに、現地従業員に出荷予定を通知する SharePoint リストにアイテムが自動的に作成されるようにします。 このリストは「出荷予定 (Expected Shipments)」と呼ぶことにして、次に示す手順で作成します。 このシリーズの今後の記事では、プログラムによってホスト Web サイトにカスタム リストを追加する方法について説明しますが、ここでは、カスタム リストを手動で追加することにします。
Fabrikam 香港店のホーム ページから、[サイト コンテンツ]>[アドインを追加]>[カスタム リスト] に移動します。
[カスタム リストの追加] ダイアログで、名前に「出荷予定」を指定してから [作成] を選択します。
[サイト コンテンツ] ページで、[出荷予定] リストを開きます。
リボンの [リスト] タブで、[リストの設定] を選択します。
[リストの設定] ページの [列] セクションで、[タイトル] 列を選択します。
[列の編集] フォームで、[列名] を「Title」から「製品」に変更して、[OK] を選択します。
[設定] ページで、[列の作成] を選択します。
このシリーズの前の記事で、リストのカスタム列を作成する方法について説明しました。 [ 予想される出荷] リストで、次の表の値を使用し、4 つの列を追加します。 その他の設定は既定値のままにしておきます。
列名 型 必須かどうか 既定値 サプライヤー 1 行テキスト 省略可 なし 数量 数値 必須 1 配送済み はい/いいえ 省略可 いいえ 在庫に追加済み はい/いいえ 省略可 いいえ 列の作成を完了したら、リストの設定ページで [サイト コンテンツ] を選択して、[サイト コンテンツ] ページを開きます。 [出荷予定] リストが開きます。
[新しいアイテム] を選択します。 アイテムの作成フォームは、次に示すものとまったく同じになります。このフォームでは、2 つのアスタリスクで、それらが必須フィールドであることを示しています。
図 1. [出荷予定] リストのアイテム作成フォーム
このリストのアイテムは手動で作成しないので、[キャンセル] をクリックします。
アイテムを SharePoint リストに挿入する
アドインに、香港ストアの受注が企業レベルで追加されたときに必ず [ 予想される出荷] リストにアイテムを作成する関数を追加しました。
ソリューション エクスプローラーで、OrderForm.aspx.cs ファイルを開きます。
Microsoft.SharePoint.Client の using ステートメントをファイルの先頭に追加します。
btnCreateOrder_Click メソッドで、
CreateOrder
の呼び出しの直後に次の行を追加します。 CreateExpectedShipment メソッドは、この次の手順で作成します。CreateExpectedShipment(txtBoxSupplier.Text, txtBoxItemName.Text, quantity);
OrderForm
クラスに、次のメソッドを追加します。private void CreateExpectedShipment(string supplier, string product, UInt16 quantity) { using (var clientContext = spContext.CreateUserClientContextForSPHost()) { List expectedShipmentsList = clientContext.Web.Lists.GetByTitle("Expected Shipments"); ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation(); ListItem newItem = expectedShipmentsList.AddItem(itemCreateInfo); newItem["Title"] = product; newItem["Supplier"] = supplier; newItem["Quantity"] = quantity; newItem.Update(); clientContext.ExecuteQuery(); } }
このコードについては、次の点に注意してください。
- ListItem オブジェクトはコンストラクターを使用して作成されません。 これはパフォーマンス上の理由によるものです。 ListItem オブジェクトには、多数のプロパティが含まれています (それらのプロパティには既定値が設定されています)。 コンストラクターを使用すると、ExecuteQuery メソッドでサーバーに送信される XML メッセージに、オブジェクト全体が含まれるようになります。
- ListItemCreationInformation オブジェクトは、サーバーで ListItem オブジェクトを作成する際に必要最小限の既定値以外の値のみが含まれている軽量オブジェクトです。 ListItem オブジェクトを作成する行が存在しているように見えますが、前述したように、この行ではサーバーに送信されるメッセージにいくつかの XML マークアップを追加しているだけです。 ListItem オブジェクトは、サーバー上に作成されます。
- ListItem オブジェクトはクライアントに差し戻す必要がないため、ClientContext.Load メソッドの呼び出しはありません。
- コードで明示的に [配送済み] または [在庫に追加済み] フィールドを設定する必要はありません。これらのフィールドの既定値は [いいえ] であり、その値がここで必要になるためです。
削除されたコンポーネントをチェックする
SharePoint リストのリスト所有者特権を持つすべてのユーザーは、リストを削除できます。 また、リストがアドインによってホスト Web に展開されている場合、ホスト Web の Web サイト所有者はそれを削除できます。 これは、所有者がリストによって提供される機能なしで実行することを決定した場合に発生する可能性があります。 (所有者が考えを変えた場合は、SharePoint ごみ箱から復元できます)。
CreateExpectedShipment メソッドは、[出荷予定] リストの有無に依存しています。 Web サイトの所有者が、このリストを削除したとします。 その後で、アドインの [注文フォーム] で注文が追加されると、CreateExpectedShipment メソッドが呼び出されて、SharePoint Web サイトに [出荷予定] リストが存在しないというメッセージを含む例外がスローされます。
このメソッドでは、何を実行するにも最初に expectedShipmentsList
の有無をチェックする必要があります。 CSOM を使用している場合、次のような単純な構造でこのチェックを行 うわけではありません 。
if (expectedShipmentsList != null) { ... }
その代わりに、ConditionalScope という特殊な CSOM を使用する必要があります。 その理由は、CSOM のバッチ処理システムに接続されるためです。これについては、このシリーズの前の記事で説明しています (「クライアント側のランタイムとバッチ処理」を参照)。 ConditionalScope とバッチ処理システムは、この基礎知識シリーズの範囲外になる高度なトピックですが、このチュートリアルのシリーズを完了した後で、それらに関するドキュメントを MSDN で参照することをお勧めします。
リストの有無を確認する別の方法があります。GetByTitle メソッドを使用してリストへの参照を取得する代わりに、次のようなコードを使用して、指定した名前のリストが、Web サイトの「リストのリスト」にあるかどうかを確認できます。
var query = from list in clientContext.Web.Lists
where list.Title == "Expected Shipments"
select list;
IEnumerable<List> matchingLists = clientContext.LoadQuery(query);
clientContext.ExecuteQuery();
if (matchingLists.Count() != 0)
{
List expectedShipmentsList = matchingLists.Single();
// Do something with the list.
}
clientContext.ExecuteQuery();
前のコードには、ConditionalScope クラスの複雑化を回避できるという長所があります。また、このコードは、このシリーズ記事の別の場所でそのまま使用しています。 ただし、短所もあります。このコードでは if ステートメントで確認する値を取得するためだけに、ExecuteQuery を追加で呼び出す必要があります。
リストの有無を確認するために、この手法を CreateExpectedShipment メソッドで使用する場合、このメソッドは ExecuteQuery を 2 回呼び出し、それぞれがリモート Web サーバーから SharePoint への HTTP 要求を実行します。 これらの要求は CSOM メソッドで最も時間がかかる部分であるため、通常は最小限にすることをお勧めします。
CreateExpectedShipment メソッドは、そのままにしておきます。ただし、実稼働のアドインでは、参照先のコンポーネントが削除される場合に、コードがどのように動作するかについて考慮しておく必要があります。 ごみ箱からプログラムによってリストを復元することも 1 つのオプションですが、意図的にリストを削除したユーザーに不便をかけることになります。
また、例外を回避するために何もしないことが最善である可能性も考慮する必要があります。 SharePoint からの例外は、リストを削除するとアドインの一部が壊れることをユーザーに警告しますが、削除を行ったユーザーはこのことを認識していない可能性があります。 次に、ユーザーはごみ箱からリストを復元するか、または機能しなくなった部分抜きでアドインを実行するかを決定できます。
Web サイトを管理するためのアクセス許可を要求する
前述したように、アドインがリストのスコープで「読み取り」または「書き込み」のアクセス許可を要求したときに、SharePoint はユーザーにアドインを信頼するように求めるダイアログを表示します。そのダイアログには、アドインがアクセスするリストをユーザーが選択するドロップダウンリストが含まれています。 選択できるリストは 1 つのみです。 ただし、チェーンストア アドインは、2 つの異なるリストに書き込みを実行するようになっています。 複数のリストへのアクセス権を取得するために、アドインでは Web のスコープのアクセス許可を要求する必要があります。 次の手順を実行します。
- ソリューション エクスプローラーで、ChainStore プロジェクトの AppManifest.xml ファイルを開きます。
- [アクセス許可] タブを開いて、[スコープ] フィールドのドロップダウンから [Web] を選択します。
- [アクセス許可] フィールドで、ドロップダウンから [書き込み] を選択します。
- ファイルを保存します。
アドインの実行とアイテムの作成のテスト
F5 キーを使用して、アドインを展開して実行します。 Visual Studio は、IIS Express でリモート Web アプリケーションをホストして、SQL Express で SQL データベースをホストします。 また、テスト用 SharePoint サイトにアドインを一時的にインストールして、すぐにアドインを実行します。 開始ページが表示される前に、アドインへのアクセス許可を付与するように求めるダイアログが表示されます。
アドインの開始ページが開いたら、ページの下部にある [注文フォーム] リンクをクリックします。
フォームに何らかの値を入力してから、[注文] を選択します。
ブラウザーの [戻る] ボタンを使用して開始ページに戻って、上部にあるクロム コントロールで [サイトに戻る] を選択します。
香港店のホーム ページから、[サイト コンテンツ] ページに移動して、[出荷予定] リストを開きます。 注文に対応するアイテムがリストに表示されるようになりました。 次のスクリーンショットは、その一例を示しています。
図 2. 1 つのアイテムを含む出荷予定の一覧
デバッグ セッションを終了するには、ブラウザー ウィンドウを閉じるか、Visual Studio でデバッグを停止します。 F5 キーを選択するたびに、Visual Studio は以前のバージョンのアドインを取り消し、最新のバージョンをインストールします。
ソリューション エクスプローラーでプロジェクトを右クリックして、[取り消し] を選択します。
次の手順
次の記事では、SharePoint ページに Web パーツとしてリモートの受注フォームを表示する方法について説明します (「プロバイダー向けのホスト型アドインにアドイン パーツを含める」)。