プロバイダー向けのホスト型アドインに最初の実行ロジックを追加する

これは、プロバイダー ホスト型の SharePoint アドインの開発の基本に関する記事のシリーズの 8 番目です。SharePoint アドイン とこのシリーズの前の記事 (プロバイダー ホスト型の SharePoint アドインの作成を始めるにある記事) をよく理解しておいてください。

注:

プロバイダー ホスト型アドインに関するこのシリーズに沿って作業してきた場合は、このトピックでも引き続き使用できる Visual Studio ソリューションを既に所有しています。 また、SharePoint_Provider-hosted_Add-Ins_Tutorials でリポジトリをダウンロードして BeforeFirstRunLogic.sln ファイルを開くこともできます。

この記事では、チェーン ストア SharePoint アドインの開始ページに、アドインの現在のインスタンスが初めて実行されているのかどうかを確認するコードを追加します。 初めて場合は、コードで [現地の従業員] リストとカスタムのリボン ボタンを展開します。

SharePoint コンポーネントを展開するための基本クラスを作成する

注:

Visual Studio のスタートアップ プロジェクトの設定は、ソリューションが開かれるたびに、既定値に戻される傾向があります。 このシリーズ記事のサンプル ソリューションを再開した直後は、次の手順を必ず実行してください。

  1. ソリューション エクスプローラーの上部にあるソリューション ノードを右クリックして、[スタートアップ プロジェクトの設定] を選択します。
  2. 3 つすべてのプロジェクトが [アクション] 列で [開始] に設定されていることを確認します。
  1. ソリューション エクスプローラー[ChainStoreWeb] プロジェクトで、[ユーティリティ] フォルダーを右クリックして、[項目の追加]>[既存の項目] の順に選択します。

  2. ファイル エクスプローラーで、ソリューション フォルダーの [ChainStoreWeb] フォルダーに移動して、[ユーティリティ] フォルダーを開きます。

  3. SharePointComponentDeployer.cs を選択してから、[追加] をクリックします。

  4. ファイル SharePointComponentDeployer.cs を開きます。 企業データベースの テナント 表でアドインのバージョンを取得および設定する、1 つの静的クラスと 2 つの静的メソッドがあります。 このシリーズの記事は、ASP.NET や SQL Server/Azure のプログラミングを説明することが目的ではないため、これらのメソッドについては説明しません。

  5. 次の using ステートメントをファイルの先頭に追加します。

      using System.Web;
      using System.Linq;
      using System.Collections.Generic;
      using Microsoft.SharePoint.Client;
    
  6. SharePointComponentDeployer クラスの先頭に、次の 2 つの静的フィールドを追加します。 これらは、どちらもアドインの開始ページの Page_Load メソッドで初期化されます。

      internal static SharePointContext sPContext;
      internal static Version localVersion;
    

    このコードについては、次の点に注意してください。

    • 最初のフィールドは、SharePoint で CRUD 操作を実行するために必要になる SharePointContext オブジェクトを保持します。

    • 2 番目のフィールドは、ホスト Web にインストールされたアドインのバージョン番号を保持します。 この値の初期値は、インストール ハンドラーがテナントを登録するときに企業の Tenants テーブルに記録する既定値 (0000.0000.0000.0000) と異なるものにします。 たとえば、アドインの最初のバージョンは 1.0.0.0 になります。

  7. 企業の テナント テーブルに現在記録されているアドインのバージョンを保持するために、次の静的プロパティを作成します。 この値を取得および設定するために、既にファイルに入っている 2 つのメソッドを使用します。

      internal static Version RemoteTenantVersion
    {
        get
        {
            return GetTenantVersion();
        }
        set
        {
            SetTenantVersion(value);
        }
    }
    
  8. ここで、次に示す IsDeployed プロパティを作成します。

      public static bool IsDeployed
    {
        get
        {
            if (RemoteTenantVersion < localVersion)
                return false; 
            else
                return true; 
        }
    }
    

    このコードについては、次の点に注意してください。

    • アドインの開始ページの Page_Load メソッドは、このプロパティの値を使用してアドインが初めて実行されているかどうかを判断します。 false の値は、現在のホスト Web でアドインが実行されたことがないことを示すため、そのアドインのコンポーネントを展開する必要があります。

    • 判断基準は、Tenants テーブルに登録されたバージョン番号が、実際にインストールされているバージョンよりも小さいかどうかです。 初めてアドインを実行する場合は小さくなります。 この後の手順で作成するコードは、実際にインストールされているものと同じバージョンに Tenants テーブルのバージョンを設定するため、アドインをもう一度実行すると、IsDeployedtrue を返して、展開ロジックは再実行されなくなります。

  9. SharePointComponentDeployer クラスに、次のメソッドを追加します。 このメソッドの最後の処理で、企業のデータベースに登録されたテナントのバージョン (0000.0000.0000.0000) とホスト Web のアドインの実際のバージョン (1.0.0.0) が同じになるように更新しています。 このメソッドは、この後の手順で完成させます。

      internal static void DeployChainStoreComponentsToHostWeb(HttpRequest request)
    {
        // TODO4: Deployment code goes here.
    
        RemoteTenantVersion = localVersion;
    }
    

注:

なぜアドインがバージョン番号と "より小さい" テストを使用して、単純なはい/いいえの質問に対する答えを決定するのか疑問に思うかもしれません。"アドインは初めて実行されていますか? Tenants テーブルに、インストール ハンドラーで not-run に設定された単純な文字列フィールドを作成し、SharePoint コンポーネントの展開後に最初の実行ロジックによって 既に実行された 1 回 に変更することもできます。

このチェーン ストア アドインの場合は、単純なテストが機能します。 ただし、通常はバージョン番号を使用することをお勧めします。これは、実稼働アドインが、将来、上書き更新 (インストール後に更新) される可能性があるためです。 そうなった場合、アドイン ロジックには「未実行」と「1 回実行済み」よりも詳細な区別が必要になります。

たとえば、バージョン 1.0.0.0 から 2.0.0.0 へのアップグレードでホスト Web に別のリストを追加するとします。 これは、更新イベント ハンドラー、または「更新後の初回実行」ロジックで実行できます。 どちらの方法でも、展開ロジックでは新しいコンポーネントの展開が必要になりますが、以前のバージョンのアドインで展開済みのコンポーネントは再展開しないようにすることも必要になります。 バージョン番号 1.0.0.0 は、バージョン 1.0.0.0 のコンポーネントが展開されていますが、「更新後の初回実行」ロジックはまだ実行されていないことを示します。

基本的なスタートアップ ロジックを追加する

SharePoint ホスト Web は、リモート Web アプリケーションに、どのバージョンのアドインがインストールされているかを通知する必要があります。 そのために、クエリ パラメーターを使用します。

  1. ChainStore プロジェクトの AppManifest.xml ファイルを開きます。 デザイナーには、[クエリ文字列] ボックスの値として、プレースホルダーの {StandardTokens} が表示されます。 その末尾に、文字列 "&amp;SPAddInVersion=1.0.0.0" を追加します。

    マニフェスト デザイナーは、次のようになります。 クエリ文字列で渡すバージョン番号は、デザイナーの [バージョン] ボックスの値と一致している必要があります。 アドインを更新するときには、常に、これらの 2 つの値を大きくして同じにすることがタスクの 1 つになります。

    図 1. マニフェスト デザイナーの [全般] タブ

    マニフェスト デザイナーの [全般] タブ。[バージョン] ボックスの値は 0 0 です。[クエリ文字列] ボックスに

  2. CorporateDataViewer.aspx.cs ファイルを開いて、Page_Load メソッドの spContext オブジェクトを初期化する行の直後に次のコードを追加します。

     SharePointComponentDeployer.sPContext = spContext;
     SharePointComponentDeployer.localVersion = new Version(Request.QueryString["SPAddInVersion"]);
    
     if (!SharePointComponentDeployer.IsDeployed)
     {
         SharePointComponentDeployer.DeployChainStoreComponentsToHostWeb(Request);
     }
    

    このコードについては、次の点に注意してください。

    • 最初に、静的 SharePointComponentDeployer クラスの 2 つの静的フィールドを設定します。 SharePointComponentDeployer のコードでは SharePoint を呼び出しているため、SharePointContext オブジェクトを渡します。また、localVersion プロパティを設定するために追加したクエリ パラメーターを使用します。

    • IsDeployed が true の場合 (初回実行ロジックが既に実行されている場合) は何も実行しません。 それ以外の場合は、展開メソッドを呼び出して、ASP.NET Request オブジェクトを渡します。

プログラムを使用して SharePoint リストを展開する

  1. SharePointComponentDeployer.cs ファイルで、TODO4 を次の行に置き換えます (このメソッドは、この後の手順で作成します)。

      CreateLocalEmployeesList();
    
  2. SharePointComponentDeployer クラスに、次のメソッドを追加します。

      private static void CreateLocalEmployeesList()
    {
        using (var clientContext = sPContext.CreateUserClientContextForSPHost())
        {
            var query = from list in clientContext.Web.Lists
                        where list.Title == "Local Employees"
                        select list;
            IEnumerable<List> matchingLists = clientContext.LoadQuery(query);
            clientContext.ExecuteQuery();
    
            if (matchingLists.Count() == 0)
            {
               // TODO5: Create the list 
    
               // TODO6: Rename the Title field on the list 
    
               // TODO7: Add "Added to Corporate DB" field to the list 
    
               clientContext.ExecuteQuery();
            }
        }
    }
    

    このコードについては、次の点に注意してください。

    • ExecuteQuery の 2 つの呼び出しがあります。 1 つ目は、リストが既に存在するかどうかを判断するために必要です。 2 つ目は、リストの作成作業を行います。

    • ClientContext.LoadQuery メソッドは ClientContext.Load メソッドと似ていますが、リストなどのエンティティをクライアントに渡す代わりに、列挙可能なクエリの結果を渡します。

  3. TODO5 を次のコードに置き換えます。

      ListCreationInformation listInfo = new ListCreationInformation();
      listInfo.Title = "Local Employees";
      listInfo.TemplateType = (int)ListTemplateType.GenericList;
      listInfo.Url = "Lists/Local Employees";
      List localEmployeesList = clientContext.Web.Lists.Add(listInfo);
    

    このコードについては、次の点に注意してください。

    • ListCreationInformation クラスは、このシリーズの前の記事で示した ListItemCreationInformation クラスに似ています。 このクラスは、Web アプリケーションから SharePoint に情報を送信する場合に、完全な List クラスよりも適している軽量クラスです。

    • "To Do" リストのためのタスク型や予定表のためのイベント型など、リスト テンプレートには多数の型があります。 [ ローカル従業員] リストは、最も簡単なジェネリック型に基づきます。

    • ListCreationInformation.Url プロパティは、ホスト Web への 相対的なリストの URL を保持します。 "Lists/LocalEmployees" を指定することで、コードでは https://{SharePointDomain}/hongkong/_layouts/15/start.aspx#/Lists/Local%20Employees へのリストの完全 URL を設定しています。

  4. を次のコードに置き換えます TODO6 。これは、"Title" フィールド (列) のパブリック名を "Title" から "Name" に変更します。これは、リストを手動で作成したときに [ リストの設定] ページで行った操作です。

      Field field = localEmployeesList.Fields.GetByInternalNameOrTitle("Title");
      field.Title = "Name";
      field.Update();
    
  5. また、[企業 DB に追加済み] というフィールドも手動で作成しました。 これをプログラムで行うには、 の代わりに次のコードを TODO7追加します。

          localEmployeesList.Fields.AddFieldAsXml("<Field DisplayName='Added to Corporate DB'"
                                                 +"Type='Boolean'>"
                                                 + "<Default>FALSE</Default></Field>",
                                                 true,
                                                 AddFieldOptions.DefaultValue);
    

    このコードについては、次の点に注意してください。

    • このフィールドの主なプロパティは、XML BLOB で指定されます。 これは、SharePoint のレガシ アーキテクチャです。Web サイト、リスト、フィールド、コンテンツ タイプ、その他ほとんどの種類の SharePoint コンポーネントは XML として定義されます。 ここでは、フィールドの表示名、データ型、および既定値を指定しています。

    • 2 つ目のパラメーターでは、フィールドがリストの既定のビューで表示されるかどうかを決定します。 ここでは、true に設定しています。

    • 3 つ目のパラメーターでは、どのコンテンツ タイプにフィールドが追加されるかを決定します。 DefaultValue を渡すことで、リストの既定のコンテンツ タイプにのみ追加されることを示します。

  6. 前述したように、既定では [企業 DB に追加済み][いいえ] (false) ですが、アドインのカスタム リボン ボタンは、従業員を企業のデータベースに追加した後で、その設定を [はい] にします。 このシステムは、ユーザーがフィールドの値を手動で変更できない場合にのみ最適に機能します。 そのようにするには、[現地の従業員] リストのアイテムの作成用および編集用のフォームで、このフィールドを非表示にします。 これは、次のコードに示すように、最初のパラメーターに別の属性を 2 つ追加することで実現しています。

      localEmployeesList.Fields.AddFieldAsXml("<Field DisplayName='Added to Corporate DB'" 
                                             + " Type='Boolean'"  
                                             + " ShowInEditForm='FALSE' "
                                             + " ShowInNewForm='FALSE'>"
                                             + "<Default>FALSE</Default></Field>",
                                             true,
                                             AddFieldOptions.DefaultValue);
    
  7. CreateLocalEmployeesList 全体は、次のようになります。

           private static void CreateLocalEmployeesList()
         {
             using (var clientContext = sPContext.CreateUserClientContextForSPHost())
             {
                 var query = from list in clientContext.Web.Lists
                             where list.Title == "Local Employees"
                             select list;
                 IEnumerable<List> matchingLists = clientContext.LoadQuery(query);
                 clientContext.ExecuteQuery();
    
                 if (matchingLists.Count() == 0)
                 {
                     ListCreationInformation listInfo = new ListCreationInformation();
                     listInfo.Title = "Local Employees";
                     listInfo.TemplateType = (int)ListTemplateType.GenericList;
                     listInfo.Url = "LocalEmployees";
                     List localEmployeesList = clientContext.Web.Lists.Add(listInfo);
    
                     Field field = localEmployeesList.Fields.GetByInternalNameOrTitle("Title");
                     field.Title = "Name";
                     field.Update();
    
                     localEmployeesList.Fields.AddFieldAsXml("<Field DisplayName='Added to Corporate DB'" 
                                                             + " Type='Boolean'"  
                                                            + " ShowInEditForm='FALSE' "
                                                            + " ShowInNewForm='FALSE'>"
                                                            + "<Default>FALSE</Default></Field>",
                                                             true,
                                                             AddFieldOptions.DefaultValue);
                     clientContext.ExecuteQuery();
                 }
             }
         }
    

カスタム ボタンをプロジェクトから一時的に削除する

この次の記事で説明する技術的な理由により、ここで作成したカスタム ボタンは、プログラムで展開されたリストのリボンに配置しているとインストールできなくなります (修正が必要になります)。 これを一時的にプロジェクトから削除して、初回実行ロジックをテストできるようにします。 これは、この次の記事で元に戻します。

  • ソリューション エクスプローラー[ChainStore] プロジェクトで、[AddEmployeeToCorpDB] ノードを右クリックして [プロジェクトから除外] を選択します。

ホスト Web でリストを管理するアクセス許可を要求する

このアドインは、既存のリストにアイテムを追加するだけでなく、ホスト Web にリストを追加するようになったため、アドインが要求するアクセス許可を「書き込み」から「管理」に昇格する必要があります。

  1. ソリューション エクスプローラーで、ChainStore プロジェクトの AppManifest.xml ファイルを開きます。

  2. [アクセス許可] タブで、[スコープ] の値は Web のままにしますが、[アクセス許可] フィールドについてはドロップダウンから [管理] を選択します。

  3. ファイルを保存します。

アドインを実行して初回実行ロジックをテストする

  1. 香港ストアの Web サイトの [サイト コンテンツ] ページを開いて、[現地の従業員] リストを削除します。

  2. F5 キーを使用して、アドインを展開して実行します。 Visual Studio は、IIS Express でリモート Web アプリケーションをホストして、SQL Express で SQL データベースをホストします。 また、テスト用 SharePoint サイトにアドインを一時的にインストールして、すぐにアドインを実行します。 開始ページが表示される前に、アドインへのアクセス許可を付与するように求めるダイアログが表示されます。

  3. アドインの開始ページが開いたら、上部のクロム コントロールにある [サイトに戻る] リンクを選択します。

  4. [サイト コンテンツ] ページに移動します。 [ローカル従業員] リストは、初回実行時のロジックで追加されるため、既に存在します。

    注:

    リストがない、または最初に実行すべきコードが実行されていないことを示す他の症状がある場合、F5 を選択したときに [テナント] テーブルが空の状態に戻されていない可能性があります。 最も一般的な原因として、ChainCorporateDB プロジェクトが Visual Studio でスタートアップ プロジェクトとしてもはや設定されていないことが考えられます。 この修正方法については、この記事の上部にある注記を参照してください。 また、「各デバッグ セッションで企業のデータベースを再構築するため、Visual Studio を構成する」で説明されているとおり、再構築するためのデータベースが構成してあることを確認してください。

  5. リストを開き、アイテムを追加します。 新しいアイテムのフォームで、[ 会社の DB に追加済み] フィールドが存在していないため、手動で設定できないことに注意してください。 これは、アイテムの編集フォームにも同様に当てはまります。

    図 2. [ローカル従業員] リストの新しいアイテム フォーム

    [ローカル従業員] リストの新しいアイテム フォーム。[企業 DB に追加] フィールドがフォーム上に表示されなくなり、[OK] と [キャンセル] の名前フィールドとボタンのみが表示されます。

  6. ブラウザーの戻るボタンを使用して、アドインの開始ページに戻ります。

  7. 上部にあるクロム コントロールの歯車アイコンをクリックして、[アカウント設定] を選択します。

  8. [アカウント設定] ページで、[アドインのバージョンの表示] ボタンをクリックします。 バージョンは、初回実行ロジックによって変更されたため 1.0.0.0 と表示されます。

    図 3. [アカウント設定] ページ

    バージョン番号が 1.0.0.0 のアカウント設定ページ。

  9. デバッグ セッションを終了するには、ブラウザー ウィンドウを閉じるか、Visual Studio でデバッグを停止します。 F5 キーを押すたびに、Visual Studio によって、以前のバージョンのアドインが取り消され、最新のバージョンがインストールされます。

  10. このアドインおよび他の記事の Visual Studio ソリューションを操作し、それが終了したら前回のアドインを取り消すとよいでしょう。 ソリューション エクスプローラーでプロジェクトを右クリックして、[取り消し] を選択します。

次の手順

次の記事では、[現地の従業員] リボンのカスタム ボタンをアドインに戻して、リストがプログラムによって展開されるようにする方法について説明します (「プログラムを使用してプロバイダー向けのホスト型アドインにカスタム ボタンを展開する」)。