【Dataverse】Visual StudioによるDataverse Plugin(Pre Validation)

accountテーブルのtelephone1の入力チェックを作成する場合の手順は以下の通りです。
入力チェックは正規表現で「^[0-9]+$」とします。

クラスファイルはプロジェクト内に2つあっても問題ありません。
1つのAssembly(dllファイル)に2つのPluginが出来上がる形になります。
クラスファイルの中身以外は以前の手順踏襲となります。

  • クラスファイルの編集
    クラス名を変更し、開発を行います。

    1using System;
    2using System.Collections.Generic;
    3using System.Linq;
    4using System.Text;
    5using System.Threading.Tasks;
    6using System.ServiceModel;
    7using Microsoft.Xrm.Sdk;
    8using System.Text.RegularExpressions;
    9 
    10namespace MyDataversePluginVS462
    11{
    12    public class FollowupPlugin2 : IPlugin
    13    {
    14        public void Execute(IServiceProvider serviceProvider)
    15        {
    16            // プラグイン実行コンテキストの取得
    17            IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext)) as IPluginExecutionContext;
    18            if (context == null)
    19            {
    20                throw new InvalidPluginExecutionException("プラグイン実行コンテキストが取得できませんでした。");
    21            }
    22 
    23            // 組織サービスファクトリの取得
    24            IOrganizationServiceFactory serviceFactory = serviceProvider.GetService(typeof(IOrganizationServiceFactory)) as IOrganizationServiceFactory;
    25            if (serviceFactory == null)
    26            {
    27                throw new InvalidOperationException("IOrganizationServiceFactory が取得できませんでした。");
    28            }
    29 
    30            // トレーシングサービスの取得
    31            ITracingService tracingService = serviceProvider.GetService(typeof(ITracingService)) as ITracingService;
    32            if (tracingService == null)
    33            {
    34                throw new InvalidPluginExecutionException("トレーシングサービスが取得できませんでした。");
    35            }
    36 
    37            // ターゲットエンティティがAccountであるか
    38            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity account && account.LogicalName == "account")
    39            {
    40                tracingService.Trace("PhoneCheckプラグインが実行されました。");
    41 
    42                // ターゲットエンティティのCreateかどうか
    43                if (context.MessageName == "Create")
    44                {
    45                    // 電話番号フィールドが存在するか
    46                    if (account.Attributes.Contains("telephone1"))
    47                    {
    48                        string phoneNumber = account.Attributes["telephone1"] as string;
    49                        if (!string.IsNullOrEmpty(phoneNumber) && Regex.IsMatch(phoneNumber, "^[0-9]+$"))
    50                        {
    51                            tracingService.Trace("電話番号の書式は問題ありません。");
    52                        }
    53                        else
    54                        {
    55                            throw new InvalidPluginExecutionException("新規登録時は電話番号の書式は数値のみで入力してください。");
    56                        }
    57                    }
    58                    else
    59                    {
    60                        throw new InvalidPluginExecutionException("電話番号(telephone1)フィールドが存在しません。");
    61                    }
    62                }
    63                else
    64                {
    65                    throw new InvalidPluginExecutionException("プラグインが実行できませんでした。(メッセージ違い)");
    66                }
    67            }
    68            else
    69            {
    70                throw new InvalidPluginExecutionException("プラグインが実行できませんでした。(テーブル違い)");
    71            }
    72 
    73            // 処理全体をtry-catchで囲って、catchでInvalidPluginExecutionExceptionするのもあり。
    74        }
    75    }
    76}

【Dataverse】Dataverse Pluginの追加

accountテーブルのtelephone1に「81-」を付与するPluginを登録する場合の手順は以下の通りです。

  • Plugin Registration Tool起動
    Plugin Registration Toolを起動し、「CREATE NEW CONNECTION」を選択します。
    「Display list of available organizations」を選択するとMicorosft 365に接続するウィンドウが起動するのでサインインを行います。
  • dllファイルの登録
    画面上部の「Register」-「Register New Assembly」を選択します。
    コンパイル後のdllファイルを選択します。
    Sandbox、Dataverseが選択されていることを確認し、「Register Selected Plugins」を押下します。
    AssemblyとPluginが登録されます。
  • PluginのStep登録
    登録されたPluginを選択し、右クリックし、「Register New Step」を選択します。
    以下をそれぞれ設定し、「Register New Step」を押下します。
    Message:Create
    Primary Entity:account
    Event Pipeline Stage of Execution:Pre Operation
    Exection Mode:Synchronous(同期)
  • トレースログON
    D365詳細設定画面を開き、「システム」-「管理」-「カスタマイズ」を開く。
    「プラグインおよびユーザー定義ワークフロー活動の追跡」を「Off」から「All」に変更する。
    トレースログは「システム」-「カスタマイズ」-「プラグイントレースログ」で確認できる。
  • 動作確認
    Power Apps(キャンパスアプリ)、Power Apps(モデル駆動型アプリ)、Power Automateのどれで登録しても
    telephone1に登録後に「81-」が付与される。

【Dataverse】Visual StudioによるDataverse Plugin(Pre Operation)

accountテーブルのtelephone1に「81-」を付与するPluginを作成する場合の手順は以下の通りです。

  • Visual Studioの導入
    Visual Studio 2022の無料版をインストールします。
    「Visual Studio 2022」「Visual Studio Installer」「Blend for Visual Studio 2022」の3つがアプリとして表示されます。

    Visual Studio 2022
    →通常の開発用
    
    Visual Studio Installer
    →.NetFrameworkやWEBアプリ開発に必要なパッケージのインストールツール
    
    Blend for Visual Studio 2022
    →アニメーション、storyboards、behaviorsの開発用
     Visual Studio 2022のプロジェクトファイルと互換性あり
    
  • プロジェクト作成
    「クラスライブラリ(.NetFramework)」のプロジェクトを作成し、
    フレームワークに「.NetFramework4.6.2」を選択します。
  • NuGetパッケージの管理
    ソリューションエクスプローラーでプロジェクトを右クリックし、「NuGetパッケージの管理」を選択します。
    「Microsoft.CrmSdk.CoreAssemblies」の最新版をインストールします。
  • クラスファイルの編集
    クラス名を変更し、開発を行います。

    1using System;
    2using System.Collections.Generic;
    3using System.Linq;
    4using System.Text;
    5using System.Threading.Tasks;
    6using System.ServiceModel;
    7using Microsoft.Xrm.Sdk;
    8 
    9namespace MyDataversePluginVS462
    10{
    11    public class FollowupPlugin : IPlugin
    12    {
    13        public void Execute(IServiceProvider serviceProvider)
    14        {
    15            // プラグイン実行コンテキストの取得
    16            IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext)) as IPluginExecutionContext;
    17            if (context == null)
    18            {
    19                throw new InvalidPluginExecutionException("プラグイン実行コンテキストが取得できませんでした。");
    20            }
    21 
    22            // 組織サービスファクトリの取得
    23            IOrganizationServiceFactory serviceFactory = serviceProvider.GetService(typeof(IOrganizationServiceFactory)) as IOrganizationServiceFactory;
    24            if (serviceFactory == null)
    25            {
    26                throw new InvalidOperationException("IOrganizationServiceFactory が取得できませんでした。");
    27            }
    28 
    29            // トレーシングサービスの取得
    30            ITracingService tracingService = serviceProvider.GetService(typeof(ITracingService)) as ITracingService;
    31            if (tracingService == null)
    32            {
    33                throw new InvalidPluginExecutionException("トレーシングサービスが取得できませんでした。");
    34            }
    35 
    36            // イベントの種類がCreateであり、ターゲットエンティティがAccountであるか
    37            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity account && account.LogicalName == "account")
    38            {
    39                tracingService.Trace("AddPhonePrefixプラグインが実行されました。");
    40 
    41                // 電話番号フィールドが存在するか
    42                if (account.Attributes.Contains("telephone1"))
    43                {
    44                    string phoneNumber = account.Attributes["telephone1"] as string;
    45                    if (!string.IsNullOrEmpty(phoneNumber))
    46                    {
    47                        // 電話番号にプレフィックスを追加
    48                        account.Attributes["telephone1"] = "+81-" + phoneNumber;
    49                        tracingService.Trace($"電話暗号を'{phoneNumber}'から'+81-{phoneNumber}'に変更しました。");
    50                    }
    51                }
    52            }
    53            else
    54            {
    55                throw new InvalidPluginExecutionException("プラグインが実行できませんでした。");
    56            }
    57 
    58            //throw new NotImplementedException();
    59        }
    60    }
    61}
  • アセンブラの署名
    ソリューションエクスプローラーでプロジェクトを右クリックし、「プロパティ」を選択します。
    左メニューから「署名」を選択し、キーファイルに任意の名前を入力します。
    「キーファイルをパスワードで保護します」のチェックを外します。
    署名アルゴリズムはデフォルトのままで署名を行います。
  • ソリューションのビルド
    ソリューションのビルドを行います。
    プロジェクトファイルの場所にもよりますが、デフォルトの場合、以下にdllファイルが出力されます。
    C:\Users\ユーザー名\source\repos\MyDataversePluginVS462\MyDataversePluginVS462\bin\Debug

【Dataverse】VSCodeによるDataverse Plugin

  • VScodeのPlugin
    Power Platform Tools
    Japanese Language Pack for Visual Studio Code
    C# Dev Kit
    C# ※自動?
    .NET Install Tool ※自動?
  • VScodeの開発1(失敗例)

    ターミナル
    mkdir MyDataversePlugin
    cd MyDataversePlugin
    pac plugin init --skip-signing ※これでプロジェクトが自動作成 ただし、この方法は署名なし
    dotnet add package Microsoft.CrmSdk.CoreAssemblies
    dotnet add package Microsoft.CrmSdk.XrmTooling.CoreAssembly
    

    C#で開発します。

    ターミナル
    dotnet build -c Release
    

    ビルドが成功すると以下にdllファイルが作成される。
    C:\Users\ユーザ名\MyDataversePlugin\bin\Release\net462\publish\MyDataversePlugin.dll

    Plug-in Registration Tool (PRT) を起動します。

    ターミナル
    pac tool prt ※コマンド実行後にWindowsに自動インストール
    サインインは「Office365」、「Display list of avaiable organizations」を選択
    

    この後にアセンブリを登録しようとすると署名エラーとなってしまう。

  • VScodeの開発2(失敗例)

    ターミナル
    mkdir MyDataversePlugin
    cd MyDataversePlugin
    dotnet new classlib -lang C# -o . ※失敗例1との違いはココ
    dotnet add package Microsoft.CrmSdk.CoreAssemblies
    dotnet add package Microsoft.CrmSdk.XrmTooling.CoreAssembly
    

    C#で開発します。

    ターミナル
    dotnet build -c Release
    

    ビルドが成功すると以下にdllファイルが作成される。
    C:\Users\ユーザ名\MyDataversePlugin\bin\Release\net462\publish\MyDataversePlugin.dll

    Plug-in Registration Tool (PRT) を起動します。

    ターミナル
    pac tool prt ※コマンド実行後にWindowsに自動インストール
    サインインは「Office365」、「Display list of avaiable organizations」を選択
    

    この後にアセンブリを登録しようとすると参照ライブラリのバージョンでエラーとなってしまう。

  • 失敗原因

    ビルド時に作成されるフォルダが「net462」となっているように
    .NETFrameworkが4.62になっている必要があるようです。
    VScodeインストールした際に.NET9.0をインストールしていました。

    .NETFrameworkはWindows専用であるのに対し、
    .NETはクロスプラットフォーム(Windows, Linux, macOS)の違いがあるようです。


    またアセンブリにもパスワードなしの署名が必要なようです。


    以下の参照は不要。
    dotnet add package Microsoft.CrmSdk.XrmTooling.CoreAssembly

  • 参考サイト
    https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/build-and-package
    「プラグインおよびカスタム ワークフロー活動アセンブリ プロジェクトは、.NET Framework 4.6.2 をターゲットにする必要があります」の記述あり。

    https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/tutorial-write-plug-in
    上記のサイトを見るとVisual Studioを使っていたのでVisual Studio2022を使うことにしました。
    プロジェクトを作成する際、.NETクラスライブラリではなく、
    .NETFrameworkクラスライブラリプロジェクトを作成することに注意。