Partager via


Dynamics CRM 2013/Fall '13 ユーザー定義アクション その 5

みなさん、こんにちは。

今回はプラグインおよびスクリプトより操作を呼び出す方法
について紹介します。前回までの内容からの続きとなります
のでご注意ください

Dynamics CRM 2013/Fall '13 ユーザー定義アクション その 1
Dynamics CRM 2013/Fall '13 ユーザー定義アクション その 2
Dynamics CRM 2013/Fall '13 ユーザー定義アクション その 3
Dynamics CRM 2013/Fall '13 ユーザー定義アクション その 4

また今回はプラグインの開発、およびスクリプト開発の経験
がある前提となります。

概要

プラグインやスクリプトからユーザー定義アクションを実行
する理由は、プロセスを1か所で管理できるためです。実際
リアルタイムワークフローを利用することでプラグインから
操作を呼び出すのと同じ処理ができますし、ワークフローを
手動実行しても結果は同じです。但しその場合ワークフロー
定義が複数存在するため管理性が低下します。

プラグインからの呼び出し

プラグインから操作を呼び出す場合、メッセージ名を解決する
には crmsvcutil にて操作を取得する必要がありますが、複数の
アセンブリに対して同じファイルを含めることはサイズの面、
管理の面から望ましくないため、実行時に解決させる方法が
あります。

尚、この手法は通常の SDK アプリケーションでも同様に利用
可能です。

1. Visual Studio を開き、C# クラスライブラリプロジェクトを
新規に作成します。ここでは MyPlugin としました。

2. 参照に Microsoft.Xrm.Sdk.dll アセンブリを含めます。

3. 参照に System.Runtime.Serialization を含めます。

4. 以下コードを MyPlugin.cs に貼り付けます。

using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyPlugin
{
    public class MyPlugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            // トレースサービスの作成
            ITracingService tracingService =
            (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            // 実行コンテキストの取得
            IPluginExecutionContext context = (IPluginExecutionContext)
            serviceProvider.GetService(typeof(IPluginExecutionContext));

            // コンテキストの入力パラメーターがエンティティか確認
            if (context.InputParameters.Contains("Target") &&
                context.InputParameters["Target"] is Entity)
            {
                // 入力パラメーターのエンティティを取得
                Entity entity = (Entity)context.InputParameters["Target"];

                // エンティティがサポート案件であることを確認
                if (entity.LogicalName != "incident")
                    return;

                // 組織サービスの取得
                IOrganizationServiceFactory serviceFactory =
                    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                try
                {
                    // エスカレーション担当者の GUID を取得するロジックをここに記述
                    // 結果として GUID を取得したと想定
                    Guid escalationEngineer = new Guid("F5D307DA-E434-E311-904F-D89D676560BC");

                    // 操作に紐づく要求の作成
                    // 操作名のみ指定。new_escalateIncidentRequest ではない点に注意
                    OrganizationRequest request = new OrganizationRequest("new_escalateIncident");
                    // アクションのターゲットとして取得したサポート案件を指定
                    request["Target"] = new EntityReference("incident", entity.Id);
                    // 要求の入力パラメータとして EscalationEngineer を設定
                    request["EscalationEngineer"] = new EntityReference("systemuser", escalationEngineer);
                    // 操作に紐づく応答の取得
                    service.Execute(request);
                }
                catch (Exception ex)
                {
                    tracingService.Trace("MyPlugin: {0}", ex.ToString());
                     throw;
                }
            }
        }
    }
}

5. MyPlug プロジェクトより署名をします。

6. コンパイルを行います。

7. プラグイン登録ツールよりコンパイルしたアセンブリを登録します。

8. 任意のメッセージに対してステップを追加します。今回はテスト
目的でサポート案件の更新に対して登録しました。

image

9. 任意のサポート案件を更新し、結果としてエスカレーションが発生
することを確認します。

スクリプトからの利用

スクリプトから操作を呼び出す場合は、SOAP エンドポイントを利用
する必要があります。概要については以下のリンクを参照してください。

チュートリアル: JavaScript を使用した Web リソースの SOAP エンドポイントの使用
https://msdn.microsoft.com/ja-jp/library/gg594434.aspx

今回作成した操作を呼び出すには以下のようなリクエストを作成します。

var caseId = “<サポート案件の GUID>”
var escalationengineerId = "<エスカレーション担当者の GUID>";

var requestMain = ""
        requestMain += "<s:Envelope xmlns:s=\"https://schemas.xmlsoap.org/soap/envelope/\">";
        requestMain += "  <s:Body>";
        requestMain += "    <Execute xmlns=\"https://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"https://www.w3.org/2001/XMLSchema-instance\">";
        requestMain += "      <request xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">";
        requestMain += "        <a:Parameters xmlns:b=\"https://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
        requestMain += "          <a:KeyValuePairOfstringanyType>";
        requestMain += "            <b:key>Target</b:key>";
        requestMain += "            <b:value i:type=\"a:EntityReference\">";
        requestMain += "              <a:Id>" + caseId + "</a:Id>";
        requestMain += "              <a:LogicalName> incident </a:LogicalName>";
        requestMain += "              <a:Name i:nil=\"true\" />";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "          <a:KeyValuePairOfstringanyType>";
        requestMain += "            <b:key>EscalationEngineer </b:key>";
        requestMain += "            <b:value i:type=\"a:EntityReference\">";
        requestMain += "              <a:Id>" + escalationengineerId + "</a:Id>";
        requestMain += "              <a:LogicalName>systemuser</a:LogicalName>";
        requestMain += "              <a:Name i:nil=\"true\" />";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>new_escalateIncident</a:RequestName>";
        requestMain += "      </request>";
        requestMain += "    </Execute>";
        requestMain += "  </s:Body>";
        requestMain += "</s:Envelope>";

スクリプトから操作を利用する例としてはカスタムボタンの
アクションとして指定することなどが考えられます。

まとめ

ユーザー定義アクションをうまく利用することで、開発者と
ビジネスプロセスの作成者の業務をシステムレベルでも分割
することができる他、開発工数や管理工数の削減にもつながり
ます。行える処理が増えるわけではありませんが、是非活用
してください。

- 中村 憲一郎