与 Microsoft Power Platform 开发相关,旨在深入介绍插件。 介绍插件的实施方式和场景,如何注册和部署插件,以及插件注册过程中可用的各种配置选项
一.简介
插件是祈使逻辑,仅当声明性流程(如业务规则、流或工作流)不符合您的要求时才使用。
从根本上来说,插件只是实现 IPlugin 接口的一个 .NET 程序集,可以在 Microsoft.CrmSdk.CoreAssemblies NuGet 包中找到。 IPlugin 接口公开了一种方法“Execute”,即您可以根据您正在处理的任何活动来放置要调用的任何自定义逻辑。
下面提供了使用插件的常见场景:
-
取消活动并向用户显示错误。
-
对操作中的数据进行更改。
-
通过使用组织服务添加自动化来启动其他操作。
二.插件的替代选择
在很多情况下,插件应被视为别无它法时的最后一种选择。 尽管插件功能强大,而且如果编写得好,性能也很出色,但您必须尽可能减少放入系统中的自定义/祈使逻辑的数量,否则会影响可维护性、可升级性等。
插件的常见替代选择有:
-
工作流
-
Power Automate 流
-
计算字段和汇总字段
-
自定义操作
三.插件注意事项
插件在性能、功能和同步运行能力方面比较出色。
编写得当的插件始终是将业务逻辑应用于 Microsoft Dataverse 最有效的方式。 但是,如果编写不当,插件可能会对环境的性能造成严重的负面影响。
插件提供了声明性业务逻辑未提供的一些功能,例如在代码中高效处理外部服务。 不过,Power Automate 正快速赶上插件。
如果您的应用程序需要同步逻辑,插件可能是必要的。 但是,按需工作流也可以同步运行,您应根据您的要求考虑使用这些工作流。
四.工作流/流与插件/客户端脚本
当现有限制要求您开发插件以完成某些活动时,可能会出现以下情况。
下表可以帮助您确定何时更适合使用工作流与插件或客户端脚本。
五.事件框架
扩展平台默认行为的所有功能都依赖于事件框架。当使用工作流设计器配置工作流以响应事件而不编写代码时,该事件由事件框架提供。
作为开发人员,将使用插件注册工具来配置插件、Azure集成、虚拟表数据提供程序和Webhook,以响应事件框架提供的事件。当事件发生并且扩展被注册以响应它们时,关于操作中涉及的数据的上下文信息被传递给扩展。根据事件注册的配置方式,扩展可以修改传递到其中的数据,启动一些立即应用的自动化流程,或者定义将某个操作添加到队列中以便稍后执行。
要将事件框架用于自定义扩展,必须了解:
- 有哪些活动
- 如何处理事件
- 当事件发生时,您的自定义扩展可以使用哪种数据
- 有哪些时间和资源限制
- 如何监控性能
六.插件执行上下文
每当插件(或自定义工作流扩展)运行时,Microsoft Dataverse 将提供大量数据,其中包含有关当前操作所在的上下文的信息。 插件和自定义工作流程序集都有权访问 IWorkflowContext 类,该类可通过不同的方法访问。
在插件中,通过调用 GetService 方法,通过 Execute 方法的 IServiceProvider 参数可访问 IPluginExecutionContext。
IExecutionContext 属性
IExecutionContext 接口的两个最出色属性是 InputParameters 和 OutputParameters。 其他常用属性是 PreEntityImages、PostEntityImages 和 SharedVariables
执行上下文的所有属性都是只读的。但是 InputParameters
、 OutputParameters
和 SharedVariables
是参数集合值。您可以操作这些集合中的项的值以更改操作的行为,具体取决于插件注册的事件执行管道中的阶段。
参数集合值被定义为KeyValuePair结构。为了访问属性,您需要知道消息所公开的属性的名称。例如,要访问作为HTTP请求的一部分传递的Entity属性,您需要知道该属性的名称是 Target
。然后你可以使用如下代码访问这个值:
var entity = (Entity)context.InputParameters["Target"];
输入参数
InputParameters 包含在执行上下文的 InputParameters 集合中,并且属于实体 类型。 通过本属性,您可以在实现给定的操作之前,查看已向插件显示的实体值。
例如,如果您要验证您的数据并在验证失败时阻止其保存,您采取的步骤将类似于以下步骤:
-
注册插件以在创建和/或更新要验证的实体时在 PreValidation 阶段上运行。
-
通过读取 InputParameters 集合中的值来验证插件中的数据。 在创建时,您将需要检索目标集合。
-
如果提供的数据无效,将引发 InvalidPluginExecutionException。
或者,可能要在保存数据之前,更新实体上的值(例如从电话号码中去除特殊字符)。 您可以通过以下步骤处理本情况:
-
注册插件以在创建和/或更新要更新的实体时在 Pre-Operation 阶段上运行。
-
通过编辑 InputParameters 集合中的值来更新插件中的数据。 在创建时,您将需要检索目标集合。
输出参数
输出参数包含在执行上下文的 OutputParameters 集合中,并且属于实体 类型。 仅在发生给定操作后才提供输出参数。 因此,您只能在处理 PostOperation 阶段中的事件时使用本集合。
例如,如果要更改操作返回的值,您可以通过执行以下步骤来修改这些值:
-
注册插件以在创建和/或更新要更新的实体时在 PostOperation 阶段上运行。
-
通过编辑 OutputParameters 集合中的值来更新插件中的数据。 在创建时,您将需要检索目标集合。
共享变量
SharedVariables属性允许包含可从API或插件传递到执行管道中稍后发生的步骤的数据。由于这是一个ParameterCollection值,因此插件可以添加、读取或修改属性,以便与后续步骤共享数据。
以下示例显示如何将 PrimaryContact
值从为PreOperation步骤注册的插件传递到PostOperation步骤。
public class PreOperation : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Obtain the execution context from the service provider.
Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
// Create or retrieve some data that will be needed by the post event
// plug-in. You could run a query, create an entity, or perform a calculation.
//In this sample, the data to be passed to the post plug-in is
// represented by a GUID.
Guid contact = new Guid("{74882D5C-381A-4863-A5B9-B8604615C2D0}");
// Pass the data to the post event plug-in in an execution context shared
// variable named PrimaryContact.
context.SharedVariables.Add("PrimaryContact", (Object)contact.ToString());
}
}
public class PostOperation : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Obtain the execution context from the service provider.
Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
// Obtain the contact from the execution context shared variables.
if (context.SharedVariables.Contains("PrimaryContact"))
{
Guid contact =
new Guid((string)context.SharedVariables["PrimaryContact"]);
// Do something with the contact.
}
}
}
实体图像
当注册插件以针对事件框架运行时,您可以提供数据的不可变副本或快照。 这是理想的情况,尤其是当您需要在操作发生之前或之后引用数据值时,例如出于记录或自定义审核目的。
虽然您可以通过检索请求方法从插件中使用组织上下文检索实体值,但使用实体图像执行本任务会更加高效且建议性更强。
定义实体图像时,可以指定可用于访问特定图像的实体别名值。例如,如果您定义了一个别名为“ a
”的前实体图像,则可以使用以下代码访问 name
属性值。
var oldAccountName = (string)context.PreEntityImages["a"]["name"];
六. 编写插件
创建插件
启动 Visual Studio 2022
选择 .NET Framework 4.7.1(其他版本可能余后续微软扩展包不兼容) 作为框架,然后选择创建。
项目中去下载 NuGet 包,microsoft.crmsdk.coreassemblies
代码如下,命名空间改为自己的项目名称
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using System.Text.RegularExpressions;
using System.Runtime.Remoting.Contexts;
namespace D365PackageProject
{
public class PreOperationFormatPhoneCreateUpdate : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
//获取执行上下文
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
//检查目标的输入参数
if (!context.InputParameters.ContainsKey("Target"))
throw new InvalidPluginExecutionException("No target found");
//从输入参数中获取目标实体,然后检查其属性是否包含电话
var entity = context.InputParameters["Target"] as Entity;
if (!entity.Attributes.Contains("telephone1"))
return;
//删除用户提供的电话号码中的所有非数字字符
string phoneNumber = (string)entity["telephone1"];
var formattedNumber = Regex.Replace(phoneNumber, @"[^\d]", "");
entity["telephone1"] = formattedNumber;
}
}
}
右键单击该项目并选择属性,选择签名选项卡,然后选择新建密钥文件,在密钥文件名字段中输入 contoso.snk(任意名称即可,不具有标识性),清除使用密码保护我的密钥文件复选框,然后选择确定。
生成dll程序
注册插件
Download the powerapps-cli-1.0.msi file
使用Power Platform CLI下载并启动工具
看看安装了哪些工具
> pac tool list
ToolName Installed Version Nuget Status
CMT No N/A 9.1.0.80 not yet installed; 'pac tool CMT' will install on first launch
PD No N/A 9.1.0.104 not yet installed; 'pac tool PD' will install on first launch
PRT No N/A 9.1.0.155 not yet installed; 'pac tool PRT' will install on first launch
下载并启动PRT
> pac tool prt
Installing 9.1.0.155 version of PRT....
Shortcut in start menu created for 'Plugin Registration Tool'
Installation complete
Launched PRT (9.1.0.155).
现在我们的工具列表看起来像这样
> pac tool list
ToolName Installed Version Nuget Status
CMT No N/A 9.1.0.80 not yet installed; 'pac tool CMT' will install on first launch
PD No N/A 9.1.0.104 not yet installed; 'pac tool PD' will install on first launch
PRT Yes 9.1.0.155 9.1.0.155 ok
启动 Plug-in Registration Tool 应用程序,选择创建新连接,选择 Microsoft 365,选中显示高级复选框,提供您的凭据,然后选择登录。
选择注册,然后选择注册新程序集
选择浏览,转到您创建的类库的 Bin > Debug 文件夹,选择 D365PackageProject.dll,然后选择打开。 选择注册所选插件
展开新注册的程序集,右键单击插件,然后选择注册新步骤,为消息选择创建,为主要实体选择联系人。为执行的事件管道阶段选择 PreOperation,然后选择注册新步骤。选择关闭。
类似的创建新步骤。
测试插件
转到您的 Maker Portal 并确保选择正确的环境,选择应用
选择仪表板并打开其中一个联系人。选择 + 新建
进行测试,应该保存记录,并且商务电话应该只显示数字值。
可用事件
如在SDK for .NET中使用消息中所述,Dataverse平台中的数据操作基于消息,并且每个消息都有一个名称。有 Create
、 Retrieve
、 RetrieveMultiple
、 Update
、 Delete
、 Associate
和 Disassociate
消息,它们涵盖了对表进行的基本数据操作。对于更复杂的操作,还有专门的消息,自定义操作会添加新消息。
使用插件注册工具注册步骤时,还必须选择事件管道执行阶段。每个消息都按下表所述的4个阶段进行处理