次の方法で共有


SharePoint ワークフローからの Web サービスの呼び出し

SharePoint アドイン モデルを使用して、アドイン Web またはホスト Web 上で動作するワークフローを作成して展開できます。 これらのワークフローは、プロバイダー ホスト型アドインのリモートでホストされる部分と対話できます。

ワークフローは、次の 2 つの方法のいずれかで重要なビジネス データを含むリモート Web サービスを呼び出すこともできます。

  • アドインのリモートでホストされる部分にクエリ情報を渡す。 その後、リモート Web アプリケーションは Web サービスを呼び出してその情報を SharePoint に戻します。

  • SharePoint Web プロキシを使用して、Web サービスのクエリを実行する。 ワークフローはアドインのリモートでホストされる部分にそのクエリ結果を渡し、次にその情報を SharePoint に渡します。

Web サービスから取得した情報は SharePoint リストに保存できます。

この記事では、次の表に示すように、ワークフローから Web サービスを呼び出す方法を示す 3 つのコード サンプルについて説明します。 最初の 2 つのサンプルでは、アドインのインストール時にワークフローとリストがアドイン Web に展開されます。 最後のサンプルでは、ワークフローの基本シェルと、それをホスト Web に展開して、ホスト Web 上のリストに関連付ける方法に関する手順を示します。

ワークフローのタスクと関連サンプル

タスク サンプル
ワークフローからカスタム Web サービスを呼び出します。 Workflow.CallCustomService
ワークフローからカスタム Web サービスを呼び出し、SharePoint Web プロキシを使用して SharePoint を更新します。 Workflow.CallServiceUpdateSPViaProxy
ワークフローとホスト Web を関連付けます。 Workflow.AssociateToHostWeb

ワークフローからカスタム Web サービスを呼び出す

Workflow.CallCustomService サンプルでは、SharePoint リスト データを更新するカスタム Web サービスを呼び出すためのワークフローを作成する方法を示します。 また、プロバイダー ホスト型アドインを、アドインと一緒に展開するリモート ホスト型 Web アプリケーションを使用して Web サービスを照会するように設計する方法も示しています。 このサンプルは、Web サービスとのすべて対話を、プロバイダー向けのホスト型アドインのリモートでホストされる部分によって処理する場合に役立ちます。

このサンプルでは、リモート Web アプリケーションからのワークフローが作業開始点です。 このワークフローは、ユーザーによって送信されるクエリ情報をリモート Web アプリケーションに渡し、その情報を使用して Northwind OData Web サービスに対するクエリを作成します。 このクエリにより、指定の国の製品供給者が返されます。 その情報の受信後、リモート Web アプリケーションは、アドイン Web に既に展開されている製品供給者リストを更新します。

注:

Workflow.CallCustomService サンプル ページに、このアドインを展開するための手順が含まれています。 また、ブログ投稿「Visual Studio 2013 を使用して SharePoint 2013 ワークフローをデバッグする」の説明に従う場合、Visual Studio で F5 によるデバッグを使用してアドインの展開とテストを行うこともできます。

Workflow.CallCustomService サンプル アドインのスタート ページには、製品供給者リストを作成する国を選択可能なドロップダウン メニューが含まれています。

サンプル アドインのスタート ページを示すスクリーンショット


画面上の [作成] ボタンは、アドイン Web 上の [部品供給者] リストに新しいエントリを作成する、Controllers\PartSuppliersController.cs ファイル内の Create メソッドを呼び出します。 その後で、Create メソッドが、Services\PartSuppliersService.cs ファイルで定義された Add メソッドを呼び出します。 次の 2 つのコード例で、シーケンスを示します。

Create メソッド

public ActionResult Create(string country, string spHostUrl)
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
            using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
            {
                var service = new PartSuppliersService(clientContext);
                var id = service.GetIdByCountry(country);
                if (id == null)
                {
                    id = service.Add(country);
                    TempData["Message"] = "Part Supplier Successfully Created!";
                }
                else
                    TempData["ErrorMessage"] = string.Format("Failed to Create The Part Supplier: There's already a Part Supplier who's country is {0}.", country);

                return RedirectToAction("Details", new { id = id.Value, SPHostUrl = spHostUrl });
            }
        }


Add メソッド

public int Add(string country)
        {
            var item = list.AddItem(new ListItemCreationInformation());
            item["Country"] = country;
            item.Update();
            clientContext.ExecuteQuery();
            return item.Id;
        }


新しいリスト項目を作成すると、承認ワークフローを開始する [ワークフローの開始] ボタンがアドインに表示されます。

サンプル アドインの [ワークフローの開始] ページを示すスクリーンショット


[ワークフローの開始] ボタンを選択すると、Controllers\PartSuppliersController.cs ファイルで定義された StartWorkflow メソッドがトリガーされます。 このメソッドは、アドイン Web URL、Web サービス URL (リモート ホスト型 Web アプリケーション用であって、Northwind Web サービス用ではない)、およびコンテキスト トークン値をパッケージ化し、それらを StartWorkflow メソッドに渡します。 PartSuppliersService メソッドには、SharePoint と対話するためのコンテキスト トークンが必要です。

public ActionResult StartWorkflow(int id, Guid workflowSubscriptionId, string spHostUrl)
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext) as SharePointAcsContext;

            var webServiceUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Data" }, Request.Url.Scheme);
            var payload = new Dictionary<string, object>
                {
                    { "appWebUrl", spContext.SPAppWebUrl.ToString() },
                    { "webServiceUrl", webServiceUrl },
                    { "contextToken",  spContext.ContextToken }
                };

            using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
            {
                var service = new PartSuppliersService(clientContext);
                service.StartWorkflow(workflowSubscriptionId, id, payload);
            }

            TempData["Message"] = "Workflow Successfully Started!";
            return RedirectToAction("Details", new { id = id, SPHostUrl = spHostUrl });
        }


その後で、StartWorkflow メソッドが、ワークフロー インスタンスを作成し、ペイロード変数に格納されている 3 つの値 (appWebUrl、webServiceUrl、contextToken) をワークフローに渡します。

 {
            var workflowServicesManager = new WorkflowServicesManager(clientContext, clientContext.Web);

            var subscriptionService = workflowServicesManager.GetWorkflowSubscriptionService();
            var subscription = subscriptionService.GetSubscription(subscriptionId);

            var instanceService = workflowServicesManager.GetWorkflowInstanceService();
            instanceService.StartWorkflowOnListItem(subscription, itemId, payload);
            clientContext.ExecuteQuery();
        }


ワークフローが開始すると、リモート ホスト型 Web アプリケーションに対して POST HTTP 要求を発行します。 この要求は、ユーザーが追加したばかりの国の供給者で供給者リストを更新するように Web アプリケーションに指示します。 Controllers\DataController.cs ファイルには、この要求の内容を受信する POST メソッドが含まれています。

public void Post([FromBody]string country)
        {
            var supplierNames = GetSupplierNames(country);
            UpdateSuppliers(country, supplierNames);
        }


GetSupplierNames メソッド (Controllers\DataController.cs ファイル内) は、選択された国に関連付けられたすべての供給者向けの Northwind OData Web サービスへの LINQ クエリを作成して実行します。

private string[] GetSupplierNames(string country)
        {
            Uri uri = new Uri("http://services.odata.org/V3/Northwind/Northwind.svc");
            var entities = new NorthwindEntities(uri);
            var names = entities.Suppliers
                .Where(s => s.Country == country)
                .AsEnumerable()
                .Select(s => s.CompanyName)
                .ToArray();
            return names;
        }


その後で、UpdateSuppliers メソッドが、新たに作成されたリスト項目の Suppliers フィールドを更新します。

private void UpdateSuppliers(string country, string[] supplierNames)
        {
            var request = HttpContext.Current.Request;
            var authority = request.Url.Authority;
            var spAppWebUrl = request.Headers["SPAppWebUrl"];
            var contextToken = request.Headers["SPContextToken"];

            using (var clientContext = TokenHelper.GetClientContextWithContextToken(
                spAppWebUrl, contextToken, authority))
            {
                var service = new PartSuppliersService(clientContext);
                service.UpdateSuppliers(country, supplierNames);
            }
        }


アドイン プロジェクトの Approve Suppliers ディレクトリにある workflow.xaml ファイルのデザイン ビューを表示している場合は、(デザイン ビューの左下にある [引数] タブを選択して) 対象のワークフローに、ワークフロー引数として渡されるペイロード変数の 3 つの値が格納されていることを確認できます。

ワークフローに渡すペイロード引数を入力するための画面を示すスクリーンショット


ワークフロー承認の前に HttpSend アクティビティが発生します。 このアクティビティは、Northwind Web サービスへの呼び出しの次に、リスト項目の更新 (供給者リストを含む) への呼び出しをトリガーするリモート Web アプリケーションに POST クエリを送信します。 このアクティビティは、ワークフロー引数として渡された webServiceUrl の値に要求を送信するように構成されます。

HTTP 送信 Web サービス URL を入力するためのテキスト ボックスを示すスクリーンショット


また、POST 要求は、ワークフローの操作対象のリスト項目に格納されている国の値も渡します。

HTTP 送信アクティビティのプロパティ グリッドを示すスクリーンショット


ワークフローは、要求ヘッダー経由で、Web アプリケーションに appWebUrl と contextToken の値を送信します。 このヘッダーは、要求を送受信するためのコンテンツ タイプも設定します。

HTTP 送信アクティビティの要求ヘッダーを追加するためのグリッドを示すスクリーンショット

ワークフローが承認されると、該当リスト項目の isApproved フィールド値が true に変更されます。

ワークフローからカスタム Web サービスを呼び出し、SharePoint Web プロキシを使用して SharePoint を更新する

Workflow.CallServiceUpdateSPViaProxy サンプルは、Web サービスを照会し、その情報を SharePoint リストに SharePoint Web プロキシを介して渡すようにプロバイダー ホスト型アドインを設計する方法を示しています。

このサンプルでは、ワークフローによって直接処理されるように、Web サービスとのすべてのやり取りをカプセル化する場合に役立つタスクを示します。 Web プロキシを使用すると、ワークフロー インスタンスを更新しなくても、リモート Web アプリケーションのロジックを簡単に更新できるようになります。 プロキシを使用しておらず、Web アプリケーションのロジックを更新する必要がある場合は、既存のワークフロー インスタンスを削除してから、アドインを再展開する必要があります。 そのため、リモート Web サービスを呼び出す必要がある場合は、このデザインをお勧めします。

注:

Workflow.CallServiceUpdateSPViaProxy サンプル ページに、このアドインを展開するための手順が含まれています。 また、ブログ投稿「Visual Studio 2013 を使用して SharePoint 2013 ワークフローをデバッグする」の説明に従う場合、Visual Studio で F5 によるデバッグを使用してアドインの展開とテストを行うこともできます。

このサンプルの開始点は、リモート Web アプリケーションからのワークフローになります。 このワークフローは、ユーザーが送信したクエリ情報を Northwind OData Web サービスに渡します。 このクエリは、指定の国の製品供給者を返します。 Web サービス応答を受信後、ワークフローは応答からの情報をリモート Web アプリケーションに渡します。 次にリモート Web アプリケーションは、アドイン Web に既に展開されている製品供給者リストを更新します。

Workflow.CallServiceUpdateSPViaProxy サンプル アドインを開始すると、スタート ページに製品供給者リストを作成する国を選択可能なドロップダウン メニューが表示されます。

プロキシ ワークフロー アドインの更新を含むサンプル アドインのスタート ページを示すスクリーンショット


[作成] ボタンは、アドイン Web 上の [部品供給者] リストに新しいエントリを作成する、Controllers\PartSuppliersController.cs ファイル内のメソッドを呼び出します。 そのファイル内の Create メソッドが、Services\PartSuppliersService.cs ファイルで定義された Add メソッドを呼び出します。 次の 2 つのコード例で、両方のメソッドを示します。

Create メソッド

public ActionResult Create(string country, string spHostUrl)
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
            using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
            {
                var service = new PartSuppliersService(clientContext);
                var id = service.GetIdByCountry(country);
                if (id == null)
                {
                    id = service.Add(country);
                    TempData["Message"] = "Part Supplier Successfully Created!";
                }
                else
                    TempData["ErrorMessage"] = string.Format("Failed to Create The Part Supplier: There's already a Part Supplier who's country is {0}.", country);

                return RedirectToAction("Details", new { id = id.Value, SPHostUrl = spHostUrl });
            }
        }


Add メソッド

public int Add(string country)
        {
            var item = list.AddItem(new ListItemCreationInformation());
            item["Country"] = country;
            item.Update();
            clientContext.ExecuteQuery();
            return item.Id;
        }


新しいリスト項目を作成すると、承認ワークフローを開始する [ワークフローの開始] ボタンがアドインに表示されます。

カスタム Web サービスの [ワークフローの開始] ページを示すスクリーンショット

[ワークフローの開始] ボタンを選択すると、Controllers\PartSuppliersController.cs ファイル内の StartWorkflow メソッドがトリガーされます。 このメソッドは、アドイン Web URL と Web サービス URL (リモート ホスト型 Web アプリケーション用であって、Northwind Web サービス用ではない) をパッケージ化し、それらを Services\PartSuppliersService.cs ファイル内の StartWorkflow メソッドに渡します。 ワークフローが Web プロキシ経由でリモート Web アプリケーションと通信し、Web プロキシが要求ヘッダーにアクセス トークンを追加します。 これが、このサンプルでは、ワークフローがコンテキスト トークンを StartWorkflow メソッドに渡さない理由です。 次の例でコードを示します。

public ActionResult StartWorkflow(int id, Guid workflowSubscriptionId, string spHostUrl)
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);

            var webServiceUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Data" }, Request.Url.Scheme);
            var payload = new Dictionary<string, object>
                {
                    { "appWebUrl", spContext.SPAppWebUrl.ToString() },
                    { "webServiceUrl", webServiceUrl }
                };

            using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
            {
                var service = new PartSuppliersService(clientContext);
                service.StartWorkflow(workflowSubscriptionId, id, payload);
            }

            TempData["Message"] = "Workflow Successfully Started!";
            return RedirectToAction("Details", new { id = id, SPHostUrl = spHostUrl });
        }


StartWorkflow メソッドがワークフロー インスタンスを作成し、ペイロード変数に格納された 2 つの値 (appWebUrl と webServiceUrl) をワークフローに渡します。

public void StartWorkflow(Guid subscriptionId, int itemId, Dictionary<string, object> payload)
        {
            var workflowServicesManager = new WorkflowServicesManager(clientContext, clientContext.Web);

            var subscriptionService = workflowServicesManager.GetWorkflowSubscriptionService();
            var subscription = subscriptionService.GetSubscription(subscriptionId);

            var instanceService = workflowServicesManager.GetWorkflowInstanceService();
            instanceService.StartWorkflowOnListItem(subscription, itemId, payload);
            clientContext.ExecuteQuery();
        }


ワークフローが開始すると、承認される前に、選択された国の供給者リストを取得する Northwind Web サービスへのクエリを作成します。 その際、エンドポイント ("http://services.odata.org/V3/Northwind/Northwind.svc/Suppliers/?$filter=Country eq '" + country.Replace("'", "''") + "'&amp;$select=CompanyName") に対して OData クエリを送信する HTTPSend アクティビティを使用します。

HttpSend アクティビティは、次のようにメタデータのない JSON を指定する Accept ヘッダーを伴う GET 要求として構成する必要があります。 application/json;odata=nometadata

GET 要求として構成された HTTP 送信アクティビティ グリッドを示すスクリーンショット

HTTP 送信アクティビティの [要求ヘッダー] グリッドを示すスクリーンショット


たとえば、ユーザーが新しい供給者リスト項目で [カナダ] を選択した場合、JSON 形式の応答は次の例のようになります。

{
    value: [
        {
            CompanyName: "Ma Maison"
        },
        {
            CompanyName: "Forêts d'érables"
        }
    ]
}


ワークフローを開始すると POST HTTP 要求が作成され、この要求に、リモート ホスト型 Web アプリケーションにプロキシを介して渡す供給者リストが含まれます。 これは、Web プロキシ URL (appWebUrl + "/_api/SP.WebProxy.invoke") を照会する HttpSend アクティビティを介して行われます。

その後で、ワークフローが、カスタム サービス ペイロードを作成して渡すことによって、Northwind サービスから受け取った供給者リストを渡します。 [カスタム サービス ペイロードの作成] アクティビティのプロパティには、供給者リストと、供給者の国の ID が含まれています。

カスタム Web サービスのペイロード アクティビティのプロパティと値のグリッドを示すスクリーンショット


[WebProxy ペイロードの作成] アクティビティは、Web プロキシ URL にこのペイロードのコンテンツを渡すペイロードを作成します。

[WebProxy ペイロードの作成] アクティビティ ダイアログを示すスクリーンショット


[WebProxy ペイロード] アクティビティのプロパティは、アドイン Web URL、POST 要求のコンテンツの長さと種類、要求ヘッダーを介した要求承認の種類を指定します。

[WebProxy ペイロード] アクティビティのプロパティ グリッドを示すスクリーンショット


ワークフローは、ペイロードと要求を構築した後、WEB プロキシ URL への POST 要求として構成された HttpSend アクティビティを使用して、要求を Web プロキシに渡します。 この要求ヘッダーで、Content-Type ヘッダーと Accept ヘッダーの JSON 形式の OData を指定します。

HTTP 送信アクティビティの [要求ヘッダー] ダイアログを示すスクリーンショット


Controllers\DataController.cs ファイル内の Post メソッドが、ワークフローが Web プロキシを介して送信した要求の内容を受け取ります。 前のサンプルの Post メソッドは、Northwind から供給者リストを取得し、対応する SharePoint 供給者リストを更新するためのメソッドを呼び出しました。

このサンプルのワークフローは既に Northwind サービスに対する照会を実行しているため、今回のメソッドで必要となるのは SharePoint リストの更新のみです。 また、次のコード例に示すように、Services\PartSuppliersService.cs ファイル内の UpdateSuppliers メソッドに対して、アドイン Web URL とアクセス トークン (Web プロキシによって渡される) を渡します。

public void Post(UpdatePartSupplierModel model)
        {
            var request = HttpContext.Current.Request;
            var authority = request.Url.Authority;
            var spAppWebUrl = request.Headers["SPAppWebUrl"];
            var accessToken = request.Headers["X-SP-AccessToken"];

            using (var clientContext = TokenHelper.GetClientContextWithContextToken(spAppWebUrl, accessToken, authority))
            {
                var service = new PartSuppliersService(clientContext);
                service.UpdateSuppliers(model.Id, model.Suppliers.Select(s => s.CompanyName));
            }
        }


PartSuppliers.cs ファイル内の UpdateSuppliers メソッドは、新たに作成されたリスト項目の Suppliers フィールドを更新します。

public void UpdateSuppliers(int id, IEnumerable<string> supplierNames)
        {
            var item = list.GetItemById(id);
            clientContext.Load(item);
            clientContext.ExecuteQuery();

            string commaSeparatedList = String.Join(",", supplierNames);
            item["Suppliers"] = commaSeparatedList;
            item.Update();
            clientContext.ExecuteQuery();
        }


ワークフローが承認されると、該当リスト項目の isApproved フィールド値が true に変更されます。

ワークフローをホスト Web に関連付ける

Workflow.AssociateToHostWeb サンプルは、Visual Studio のツールを使用してワークフローをホスト Web に展開し、ホスト Web 上のリストに関連付ける方法を示しています。 このサンプルに関する手順では、Visual Studio でワークフローを作成し、それをホスト Web に展開してから、ホスト Web 上のリストに関連付ける方法が示されています。

このサンプルには、任意のリストに関連付けることができる単純なワークフローが含まれています。 このワークフローを展開するための手順では、アドインをパッケージ化してから開き、構成ファイルを編集して、手動で再パッケージ化してからホスト Web に展開することによって、Visual Studio ワークフロー ツールの現在の制限を回避する方法が示されています。

このプロジェクトを Visual Studio で開くと、どの SharePoint リストも処理できる簡単な汎用ワークフローが表示されます。 ワークフロー タスク リストのほかには、関連付けが可能なリストは展開しません。

注:

Visual Studio 2013 を使用してこのサンプルで示されているタスクを実行することはできません。 このサンプルには役立つ回避策が示されています。 Visual Studio ツールが今後更新される場合には、この回避策を使用する必要はなくなる可能性があります。

ワークフローをホスト Web に展開する

  1. プロジェクト エクスプローラーで Workflow.AssociateToHostWeb アドイン プロジェクトのショートカット メニュー (右クリック) を開き、[発行] を選択します。 [アプリをパッケージ化する] ボタンが含まれるウィンドウが表示されます。

    サンプル アドインを発行するための [アプリを発行する] ページを示すスクリーンショット

  2. [ アプリのパッケージ化] を選択すると、Visual Studio によってソリューションのディレクトリに Workflow.AssociateToHostWeb.app ファイルが bin\Debug\app.publish\1.0.0.0 作成されます。 この .app ファイルの種類は .zip ファイルです。

  3. 最初にファイル拡張子を .zip に変更してファイル コンテンツを解凍します。

  4. 解凍先ディレクトリで WorkflowManifest.xml という名前の XML ファイルを見つけて開きます。 このファイルは空です。

  5. 次の XML フラグメントをファイルに追加してから、ファイルを保存します。

       <SPIntegratedWorkflow xmlns="http://schemas.microsoft.com/sharepoint/2014/app/integratedworkflow">
         <IntegratedApp>true</IntegratedApp>
       </SPIntegratedWorkflow>
    
  6. 解凍先フォルダー内のすべてのファイルを選択し、それらのファイルをショートカット メニュー (右クリック) で開き、[送る]>[圧縮 (zip 形式) フォルダー] を選択します。

  7. 先ほど作成した zip ファイルのファイル拡張子を .app に変更します。 これで、更新した WorkflowManifest.xml ファイルが含まれる新しい Workflow.AssociateToHostWeb.app パッケージができました。

  8. アドインをアプリ カタログに追加します。

  9. アドインをホスト サイトにインストールします。

  10. ホスト サイト上のリストに移動し、ページの左上にある [リスト] 編集オプションを選択します。 [ワークフロー設定] ドロップダウン メニューが表示されます。

    リストのワークフロー設定を示すスクリーンショット

  11. ドロップダウン メニューから [ワークフローの追加] を選択します。

  12. 次の図の画像と同様の選択オプションが表示されます。 選択可能なオプション リストから Workflow.AssociateToHostWeb アドインを選択します。

    [ワークフローの追加] 設定ページを示すスクリーンショット

これで、ワークフローをホスト Web に展開し、ホスト Web 上のリストと関連付けることができました。 ワークフローを手動で起動するか、Visual Studio でワークフローを更新して他の方法で起動できます。

関連項目