插件是一种自定义业务逻辑,它与Microsoft Dynamics CRM集成以修改或扩展平台的标准行为.插件充当事件处理程序,并注册为在CRM中的特定事件上执行.插件用C#或VB编写,可以同步或异步模式运行.
你编写插件的一些场景是 :
您希望在创建或更新CRM记录时执行某些业务逻辑,例如更新记录的某些字段或更新相关记录等.
您希望在某些事件上调用外部Web服务,例如保存或更新记录.
您希望在打开任何记录时动态计算字段值.
您希望自动执行诸如向客户发送电子邮件等流程CRM中的事件.
事件框架
CRM中的事件处理框架处理同步和异步插件请求通过将其传递给事件执行管道.每当事件触发插件逻辑时,都会向CRM组织Web服务发送一条消息,可以通过其他插件或平台的任何核心操作读取或修改该消息.
插件管道阶段
整个插件管道分为多个阶段,您可以在其中注册自定义业务逻辑.指定的管道阶段指示插件执行周期的哪个阶段,您的插件代码运行.在下表中的所有指定管道阶段中,您只能在事件前和事件后注册自定义插件.您无法在Platform Core主要操作上注册插件.
事件 | 阶段名称 | 说明 |
---|---|---|
事前 | 预验证 | 管道中的阶段,用于之前要执行的插件主要系统操作.在此阶段注册的插件可以在数据库事务之外执行. |
事前 | 预操作 | 在主系统操作之前执行的插件的管道中的阶段.在此阶段注册的插件在数据库事务中执行. |
平台核心操作 | MainOperation | Intransaction,主要系统的操作,如创建,更新,删除等.在此阶段无法注册自定义插件.仅供内部使用. |
事件后 | 后期操作 | 插件管道中的阶段在主要操作后执行.在此阶段注册的插件在数据库事务中执行. |
每当CRM应用程序调用事件时(如保存或更新记录),发生以下一系列操作 :
该事件触发Web服务调用执行通过事件管道阶段(事件前,平台核心操作,事件后)传递.
信息在内部打包为OrganizationRequest消息最后发送到内部CRM Web服务方法和平台核心操作.
组织请求消息首先由事件前插件接收,可以修改信息在将其传递给平台核心操作之前.在平台核心操作之后,消息被打包为OrganizationResponse并传递给操作后插件.术后插件可以选择在将此信息传递给异步插件之前对其进行修改.
插件以上下文对象的形式接收此信息,并传递给执行进一步处理的执行方法.
完成所有插件处理后,执行将被传递回触发事件的应用程序.
插件消息
消息是插件(或业务逻辑)注册的事件.例如,您可以在Create Message of Contact实体上注册插件.每当创建新的联系人记录时,这将触发业务逻辑.
对于自定义实体,以下是基于实体是用户拥有还是组织拥有的支持消息.
消息名称 | 所有权类型 |
---|---|
Assign | 仅限用户拥有的实体 |
Create | 用户拥有和组织拥有的实体 |
Delete | 用户拥有和组织拥有的实体 |
GrantAccess | 仅限用户拥有的实体 |
ModifyAccess | 仅限用户拥有的实体 |
Retrieve | 用户拥有和组织拥有的实体 |
RetrieveMultiple | 用户拥有和组织拥有的实体 |
RetrievePrincipalAccess | 仅限用户拥有的实体 |
RetrieveSharedPrincipalsAndAccess | 仅限用户拥有的实体 |
RevokeAccess | 仅限用户拥有的实体 |
SetState | 用户拥有和组织拥有实体 |
SetStateDynamicEntity | 用户和组织拥有的实体 |
Update | 用户拥有和组织拥有的实体 |
对于默认的开箱即用实体,支持的消息超过100条.其中一些消息适用于所有实体,而其中一些实体特定于某些实体.您可以在SDK内的excel文件中找到支持消息的完整列表: SDK \Message-entity支持plug-ins.xlsx
编写插件
在本节中,我们将学习编写插件的基础知识.我们将创建一个示例插件,创建一个Task活动,以便在新客户添加到系统时跟进客户,即每当在CRM中创建新的Contactrecord时.
首先,您需要包含对 Microsoft.Xrm.Sdk 命名空间的引用. CRM SDK包含所有必需的SDK程序集.假设您已经在第2章中下载并安装了SDK,请打开Visual Studio.创建类库类型的新项目.您可以将项目命名为SamplePlugins并单击OK.
将 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 { /// A plug-in that creates a follow-up task activity when a new account is created. /// Register this plug-in on the Create message, account entity, /// and asynchronous mode. public void Execute(IServiceProviderserviceProvider) { // Obtain the execution context from the service provider. IPluginExecutionContext context =(IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); // The InputParameters collection contains all the data passed in the message request. if(context.InputParameters.Contains("Target")&& context.InputParameters["Target"]isEntity) { // Obtain the target entity from the input parameters. Entity entity = (Entity)context.InputParameters["Target"]; try { // Create a task activity to follow up with the account customer in 7 days 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; // Refer to the contact in the task activity. if(context.OutputParameters.Contains("id")) { Guid regardingobjectid = new Guid(context.OutputParameter s["id"].ToString()); string regardingobjectidType = "contact"; followup["regardingobjectid"] = new EntityReference(rega rdingobjectidType,regardingobjectid); } // Obtain the organization service reference. IOrganizationServiceFactory serviceFactory = (IOrganizationSer viceFactory)serviceProvider.GetService (typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); // Create the followup activity service.Create(followup); } catch(Exception ex) { throw new InvalidPluginExecutionException(ex.Message); } } } } }
以下是一步一步这个代码做什么和减去的步骤解释;
步骤1 : 通过将IServiceProvider对象作为其参数来实现Execute方法.服务提供者包含对您将在插件中使用的许多有用对象的引用.
步骤2 : 使用IServiceProvider的GetService方法获取IPluginExecutionContext对象.
步骤3 : 从上下文对象的InputParameters集合中获取目标实体的对象.此Entity类对象引用我们的插件将在其上注册的Contact实体记录.
步骤4 : 然后它创建一个Task实体的对象,并设置适当的主题,描述,日期,类别和aboutobjectid.关于obobjectid指示正在创建此活动记录的联系人记录.您可以看到代码使用context.OutputParameters获取父联系人记录的ID,并将其与您创建的任务实体记录相关联.
步骤5 : 使用IServiceProvider对象创建IOrganizationServiceFactory的对象.
步骤6 : 使用IOrganizationServiceFactory对象创建IOrganizationService的对象.
步骤7 : 最后,使用此服务对象的Create方法.它会创建后续活动,并将其保存在CRM中.
签署插件程序集
此部分仅适用于您注册插件的情况第一次组装.您需要使用密钥登录程序集才能部署插件.右键单击解决方案,然后单击属性.
选择左侧选项中的"签名"选项卡,然后选中"签署程序集"选项.然后,从选择强名称密钥文件选项中选择新建.
输入密钥文件名作为sampleplugins(这可以是您想要的任何其他名称).取消选中"使用密码保护我的密钥文件"选项,然后单击"确定".单击保存.
最后,构建解决方案.右击 → 建立.构建解决方案将生成程序集DLL,我们将在下一章中使用它来注册此插件.
插件中的异常处理
比不,你的插件逻辑需要处理运行时异常.对于同步插件,您可以返回 InvalidPluginExecutionException 异常,该异常将向用户显示错误对话框.错误对话框将包含您传递给异常对象的Message对象的自定义错误消息.
如果您查看我们的代码,我们会在catch块中抛出InvalidPluginExecutionException异常.
throw new InvalidPluginExecutionException(ex.Message);
结论
插件绝对是任何自定义CRM实施的关键.在本章中,我们专注于理解事件框架模型,管道阶段,消息和编写示例插件.在下一章中,我们将在CRM中注册此插件,并将其视为端到端场景.