Microsoft Dynamics CRM - 插件
插件是一种自定义业务逻辑,可与 Microsoft Dynamics CRM 集成以修改或扩展平台的标准行为。插件充当事件处理程序,并注册为在 CRM 中的特定事件上执行。插件可以用 C# 或 VB 编写,并且可以在同步或异步模式下运行。
您需要编写插件的一些场景是 −
当您创建或更新 CRM 记录时,您想要执行某些业务逻辑,例如更新记录的某些字段或更新相关记录等。
您想要在某些事件(例如保存或更新记录)上调用外部 Web 服务。
您想要在打开任何记录时动态计算字段值。
您想要自动化流程,例如在 CRM 中的某些事件上向您的客户发送电子邮件。
事件框架
CRM 中的事件处理框架通过将同步和异步插件请求传递给事件执行管道来处理它。每当事件触发插件逻辑时,都会向 CRM 组织 Web 服务发送一条消息,其他插件或平台的任何核心操作都可以读取或修改该消息。
插件管道阶段
整个插件管道分为多个阶段,您可以在这些阶段注册自定义业务逻辑。指定的管道阶段表示您的插件代码在插件执行周期的哪个阶段运行。在下表中指定的所有管道阶段中,您只能在事件前和事件后注册自定义插件。您无法在平台核心主操作上注册插件。
事件 | 阶段名称 | 描述 |
---|---|---|
事件前 | 预验证 | 在管道中,在主系统操作之前执行插件的阶段。在此阶段注册的插件可能会在数据库事务之外执行。 |
事件前 | 操作前 | 管道中的阶段,用于在主系统操作之前执行插件。在此阶段注册的插件在数据库事务内执行。 |
平台核心操作 | 主操作 | 事务中,系统的主要操作,如创建、更新、删除等。此阶段不能注册任何自定义插件。仅供内部使用。 |
事件后 | 操作后 | 管道中在主操作之后执行的插件阶段。在此阶段注册的插件在数据库事务中执行。 |
每当 CRM 应用程序调用事件(如保存或更新记录)时,都会发生以下操作序列 −
事件触发 Web 服务调用,执行通过事件管道阶段(事件前、平台核心操作、事件后)进行。
信息在内部打包为 OrganizationRequest 消息,最终发送到内部 CRM Web 服务方法和平台核心操作。
OrganizationRequest 消息首先由事件前插件接收,事件前插件可以在将信息传递给平台核心操作之前对其进行修改。平台核心操作之后,消息被打包为 OrganizationResponse 并传递给后操作插件。后操作插件可以在将此信息传递给异步插件之前选择性地修改此信息。
插件以上下文对象的形式接收此信息,并将其传递给 Execute 方法,然后进行进一步的处理。
所有插件处理完成后,执行将传递回触发事件的应用程序。
插件消息
消息是插件(或业务逻辑)注册的事件。例如,您可以在联系人实体的创建消息上注册一个插件。每当创建新的联系人记录时,这将触发业务逻辑。
对于自定义实体,以下是根据实体是用户所有还是组织所有而支持的消息。
消息名称 | 所有权类型 |
---|---|
Assign | 仅限用户所有实体 |
Create | 用户所有和组织所有实体 |
Delete | 用户所有和组织所有实体 |
GrantAccess | 仅限用户拥有的实体 |
ModifyAccess | 仅限用户拥有的实体 |
Retrieve | 用户拥有和组织拥有的实体 |
RetrieveMultiple | 用户拥有和组织拥有的实体 |
RetrievePrincipalAccess | 仅限用户拥有的实体 |
RetrieveSharedPrincipalsAndAccess | 仅限用户拥有的实体 |
RevokeAccess | 仅限用户拥有的实体 |
SetState | 用户拥有和组织拥有的实体 |
SetStateDynamicEntity | 用户拥有和组织拥有的实体 |
Update | 用户拥有和组织拥有的实体 |
对于默认的开箱即用实体,支持的消息超过 100 条。其中一些消息适用于所有实体,而另一些消息则特定于某些实体。您可以在 SDK 中的 excel 文件中找到支持的消息的完整列表:SDK\Message-entity support for plug-ins.xlsx
编写插件
在本节中,我们将学习编写插件的基础知识。我们将创建一个示例插件,该插件会创建一个任务活动,每当有新客户添加到系统中时(即,每当在 CRM 中创建新的联系人记录时),都会跟进客户。
首先,您需要包含对 Microsoft.Xrm.Sdk 命名空间的引用。CRM SDK 包含所有必需的 SDK 程序集。假设您已经在第 2 章中下载并安装了 SDK,请打开 Visual Studio。创建一个类库类型的新项目。您可以将该项目命名为 SamplePlugins,然后单击"确定"。
将 Microsoft.Xrm.Sdk 程序集的引用添加到您的项目中。该程序集位于 SDK/Bin 中。
现在,创建一个名为 PostCreateContact.cs 的类并从 IPlugin 扩展该类。到目前为止,您的代码将类似于以下内容。
您还需要添加对 System.Runtime.Serialization 的引用。添加所需的引用后,将以下代码复制到 PostCreateContact 类中。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Xrm.Sdk; namespace SamplePlugins { public class PostCreateContact:IPlugin { /// 当新账户被创建时,创建一个后续任务活动的插件。 /// 在Create消息、账户实体、 /// 和异步模式下注册此插件。 public void Execute(IServiceProviderserviceProvider) { // 从服务提供者获取执行上下文。 IPluginExecutionContext context =(IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); // InputParameters 集合包含所有数据 passed in the message request. if(context.InputParameters.Contains("Target")&& context.InputParameters["Target"]isEntity) { // 从输入参数中获取目标实体。 Entity entity = (Entity)context.InputParameters["Target"]; try { // 创建任务活动,在 7 天内跟进帐户客户 Entity followup = new Entity("task"); followup["subject"] = "Send e-mail to the new customer."; followup["description"] = "Follow up with the customer. Check if there are any new issues that need resolution."; followup["scheduledstart"] = DateTime.Now; followup["scheduledend"] = DateTime.Now.AddDays(2); followup["category"] = context.PrimaryEntityName; // 请参阅任务活动中的联系人。 if(context.OutputParameters.Contains("id")) { Guid regardingobjectid = new Guid(context.OutputParameter s["id"].ToString()); string regardingobjectidType = "contact"; followup["regardingobjectid"] = new EntityReference(rega rdingobjectidType,regardingobjectid); } // 获取组织服务参考。 IOrganizationServiceFactory serviceFactory = (IOrganizationSer viceFactory)serviceProvider.GetService (typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); // 创建后续活动 service.Create(followup); } catch(Exception ex) { throw new InvalidPluginExecutionException(ex.Message); } } } } }
以下是此代码的分步说明 −
步骤 1 − 通过将 IServiceProvider 对象作为其参数来实现 Execute 方法。服务提供商包含对您将在插件中使用的许多有用对象的引用。
步骤 2 − 使用 IServiceProvider 的 GetService 方法获取 IPluginExecutionContext 对象。
步骤 3 − 从上下文对象的 InputParameters 集合中获取目标实体的对象。此 Entity 类对象引用我们的插件将在其上注册的联系人实体记录。
步骤 4 − 然后,它创建 Task 实体的对象并设置适当的主题、描述、日期、类别和 regardingobjectid。 regardingobjectid 指示此活动记录是为哪个联系人记录创建的。您可以看到代码使用 context.OutputParameters 获取父联系人记录的 ID,并将其与您创建的 Task 实体记录关联。
步骤 5 − 使用 IServiceProvider 对象创建 IOrganizationServiceFactory 对象。
步骤 6 − 使用 IOrganizationServiceFactory 对象创建 IOrganizationService 对象。
步骤 7 − 最后,使用此服务对象的 Create 方法。它创建保存在 CRM 中的后续活动。
签署插件程序集
本节仅适用于您首次注册插件程序集的情况。您需要使用密钥登录程序集才能部署插件。右键单击解决方案,然后单击"属性"。
从左侧选项中选择"签名"选项卡,然后选中"签名程序集"选项。然后,从"选择强名称密钥文件"选项中选择"新建"。
输入密钥文件名为 sampleplugins(这可以是您想要的任何其他名称)。取消选中"使用密码保护我的密钥文件"选项,然后单击"确定"。单击"保存"。
最后,构建解决方案。右键单击并构建。构建解决方案将生成程序集 DLL,我们将在下一章中使用它来注册此插件。
插件中的异常处理
通常,您的插件逻辑需要处理运行时异常。对于同步插件,您可以返回 InvalidPluginExecutionException 异常,这将向用户显示一个错误对话框。错误对话框将包含您传递给异常对象的 Message 对象的自定义错误消息。
如果您查看我们的代码,我们会在 catch 块中抛出 InvalidPluginExecutionException 异常。
throw new InvalidPluginExecutionException(ex.Message);
结论
插件对于任何自定义 CRM 实现都至关重要。在本章中,我们重点介绍了了解事件框架模型、管道阶段、消息以及编写示例插件。在下一章中,我们将在 CRM 中注册此插件并从端到端场景查看其工作情况。