编写插件

 

发布日期: 2017年1月

适用于: Dynamics 365 (online),Dynamics 365 (on-premises),Dynamics CRM 2016,Dynamics CRM Online

插件是实现 IPlugin 接口的自定义类。 您可以使用与 .NET Framework 4.5.2 CLR 兼容的任何语言(如 Microsoft Visual C# 和 Microsoft Visual Basic .NET)编写插件。 为了能够编译插件代码,必须在项目中添加 Microsoft.Xrm.Sdk.dll 和 Microsoft.Crm.Sdk.Proxy.dll 程序集引用。 这些程序集可以在 SDK 的 SDK\Bin 文件夹中找到。下载 Microsoft Dynamics CRM SDK 包。

本主题内容

插件设计

编写基本插件

编写插件构造函数

支持脱机执行

独立(沙盒)插件的 Web 访问

使用早期绑定类型

插件程序集

插件设计

您的插件设计应考虑 Microsoft Dynamics 365(在线或本地) 中引入的“自动保存”功能。 默认情况下启用自动保存功能,但是可以在组织级别将其禁用。 启用自动保存后,不会出现“保存”按钮。 进行最后一次未保存更改 30 秒钟后,Web 应用程序将会自动保存窗体中的数据。 您可以应用窗体脚本以在窗体级别禁用自动保存行为。 根据您注册插件的方式,自动保存可能导致针对各个字段更改更加频繁地调用插件,而不是针对全部更改调用一次插件。 您应该假定,所有用户都可以随时保存任何记录,不管是使用 Ctrl+S、是通过按下保存按钮,还是通过自动保存功能自动保存。

最好的做法是对实体和最重要的特定字段注册插件或工作流。 避免为所有实体字段的更改注册插件或工作流。 如果您的现有插件或工作流是在提供自动保存之前实现的,您应重新测试该代码以验证其正确操作。 有关详细信息,请参阅 TechNet:管理自动保存

编写基本插件

以下示例演示在插件中找到的一些常见代码。 对于此示例,代码省略执行插件预期任务的所有自定义业务逻辑。 不过,代码显示了一个实现 IPlugin 接口和所需 Execute 方法的插件类。

using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;

public class MyPlugin: IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        // Extract the tracing service for use in debugging sandboxed plug-ins.
        // If you are not registering the plug-in in the sandbox, then you do
        // not have to add any tracing service related code.
        ITracingService tracingService =
            (ITracingService)serviceProvider.GetService(typeof(ITracingService));

        // 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"] is Entity)
        {
            // Obtain the target entity from the input parameters.
            Entity entity = (Entity)context.InputParameters["Target"];

            // Verify that the target entity represents an entity type you are expecting. 
            // For example, an account. If not, the plug-in was not registered correctly.
            if (entity.LogicalName != "account")
                return;

            // Obtain the organization service reference which you will need for
            // web service calls.
            IOrganizationServiceFactory serviceFactory = 
                (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            try
            {
                // Plug-in business logic goes here.
            }

            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw new InvalidPluginExecutionException("An error occurred in MyPlug-in.", ex);
            }

            catch (Exception ex)
            {
                tracingService.Trace("MyPlugin: {0}", ex.ToString());
                throw;
            }
        }
    }
}

Execute 方法的 IServiceProvider 参数是可以在插件中访问的一些有用服务对象的容器。 服务提供程序包含对执行上下文、IOrganizationServiceFactoryITracingService 等的实例引用。 示例代码演示如何从服务提供程序参数获取对执行上下文 IOrganizationServiceITracingService 的引用。 有关跟踪服务的详细信息,请参阅调试插件

执行上下文包含有关导致插件执行的事件和管道当前处理的消息中包含的数据的大量信息。 有关数据上下文的详细信息,请参阅了解传递给插件的数据上下文

从服务提供程序获取组织 Web 服务引用时,平台提供正确的 Web 服务 URL 和网络凭据。 不支持实例化您自己的 Web 服务代理,因为它会导致死锁和身份验证问题。 获取组织服务引用后,可以使用它对组织 Web 服务执行方法调用。 可以通过向 Web 服务发出一个或多个消息请求来检索或更改单个 Microsoft Dynamics 365 组织中的业务数据。 有关消息请求的详细信息,请参阅将消息(请求和响应类)与 Execute 方法结合使用

典型的插件应该访问上下文中的信息、执行所需的业务操作和处理异常。 有关处理插件中的异常的详细信息,请参阅处理插件中的异常示例:创建基本插件主题中提供了更完整的插件示例。

重要

为了提高性能,Microsoft Dynamics 365 缓存插件实例。 插件的 Execute 方法应编写为无状态方法,因为不是每次调用插件时都调用构造函数。 此外,多个系统线程还可能同时执行插件。 有关每次调用的所有状态信息都存储在上下文中,因此您不应该使用全局变量或者尝试在成员变量中存储任何数据以在下一插件调用期间使用,除非该数据是从提供给构造函数的配置参数获取的。 插件注册的更改将导致插件重新初始化。

编写插件构造函数

Microsoft Dynamics 365 平台支持可选的插件构造函数,该函数接受一个或两个字符串参数。 如果编写此类构造函数,则可以在运行时向插件传递任何信息字符串。

以下示例显示构造函数的格式。 在此示例中,插件类名为 SamplePlugin。

public SamplePlugin()
public SamplePlugin(string unsecure)
public SamplePlugin(string unsecure, string secure)

构造函数的第一个字符串参数包含公共(不安全)信息。 第二个字符串参数包含非公共(安全)信息。 在这里,安全是指加密的值,而不安全是指未加密的值。 如果使用带脱机访问功能的 Microsoft Dynamics 365 for Microsoft Office Outlook,则 Dynamics 365 for Outlook 脱机时安全字符串不会传递到执行的插件。

在这些字符串中传递到插件构造函数的信息是在 Microsoft Dynamics 365 中注册插件时指定的。 使用插件注册工具注册插件时,可以在“注册新步骤”窗体提供的“安全配置”和“不安全配置”字段中输入安全信息和不安全信息。 使用 Microsoft Dynamics 365 SDK 以编程方式注册插件时,SdkMessageProcessingStep.Configuration 包含不安全的值,SdkMessageProcessingStep.SecureConfigId 引用包含安全值的 SdkMessageProcessingStepSecureConfig 记录。

支持脱机执行

您可以在联机模式、脱机模式或两种模式下注册要执行的插件。 脱机模式仅在带脱机访问功能的 Microsoft Dynamics 365 for Microsoft Office Outlook 上受支持。 插件代码可以通过检查 IsExecutingOffline 属性来检查它是否在脱机模式下执行。

在设计将注册为联机和脱机执行的插件时,请记住插件可以执行两次。 第一次是在 带脱机访问功能的 Microsoft Dynamics 365 for Microsoft Office Outlook 脱机时。 当 Dynamics 365 for Outlook 联机并在 Dynamics 365 for Outlook 和 Microsoft Dynamics 365 服务器之间进行同步时将再次执行插件。 您可以检查 IsOfflinePlayback 属性,以确定是否由于此同步而执行了插件。

独立(沙盒)插件的 Web 访问

如果您计划在沙盒中注册插件,仍可以从插件代码访问 Web 地址。 在插件代码中,您可以使用在插件隔离、信任和统计信息所述的 Web 访问限制范围内提供 Web 访问的任何 .NET Framework 类。 例如,以下插件代码下载网页。


// Download the target URI using a Web client. Any .NET class that uses the
// HTTP or HTTPS protocols and a DNS lookup should work.
using (WebClient client = new WebClient())
{
    byte[] responseBytes = client.DownloadData(webAddress);
    string response = Encoding.UTF8.GetString(responseBytes);
System_CAPS_security 安全性 说明

要使沙盒插件能够访问外部 Web 服务,安装沙盒处理服务角色的服务器必须向 Internet 公开,并且沙盒服务使用的帐户必须能够访问 Internet。 只需要端口 80 和 443 上的出站连接。 不需要入站连接访问。 使用 Windows 防火墙控制面板启用位于 %PROGRAMFILES%\Microsoft Dynamics 365\Server\bin folder下的服务器上的 Microsoft.Crm.Sandbox.WorkerProcess 应用程序的外站连接。

使用早期绑定类型

若要在插件代码中使用早期绑定 Microsoft Dynamics 365 类型,只需在 CrmSvcUtil 插件项目中包含使用 Microsoft Visual Studio 程序生成的类型文件即可。

按如下方式处理晚期绑定实体到早期绑定实体的转换:

Account acct = entity.ToEntity<Account>();

在前一行代码中,acct 变量是早期绑定类型。 分派给 Entity 的所有 IPluginExecutionContext 值必须是晚期绑定类型。 如果将早期绑定类型分派给上下文,则将出现 SerializationException。 有关详细信息,请参阅了解传递给插件的数据上下文。 确保您没有混用类型和在需要晚期绑定类型的位置使用早期绑定类型,如以下代码所示。

context.InputParameters["Target"] = new Account() { Name = "MyAccount" }; // WRONG: Do not do this.

在上面的示例中,您不希望在应该存储晚期绑定实例的插件上下文中存储早期绑定实例。 这样做是为了避免在调用插件之前和从插件返回到平台时要求平台在早期绑定和晚期绑定类型之间转换。

插件程序集

程序集中可以包含一个或多个插件类型。 注册和部署插件程序集后,插件可以执行预期操作以响应 Microsoft Dynamics 365 运行时事件。

System_CAPS_security 安全性 说明

在 Microsoft Dynamics 365 中,每个人必须都可以读取插件程序集,插件程序集才能正常工作。 因此,出于安全考虑,一般不在插件代码中包含任何系统登录信息、凭据信息或公司商业机密。

每个插件程序集注册并部署到 Microsoft Dynamics 365 之前,必须使用 Microsoft Visual Studio 中的项目属性页的“签名”选项卡或“强名称”工具进行签名。 有关“强名称”工具的详细信息,请从 Microsoft Visual Studio 命令提示符窗口运行 sn.exe 程序(不需要使用参数)。

如果您的程序集包含可以在 Dynamics 365 for Outlook 脱机时执行的插件,则 Microsoft Dynamics 365 平台会对程序集实施附加安全措施。 有关详细信息,请参阅演练:配置脱机插件的程序集安全性

另请参阅

插件开发
了解传递给插件的数据上下文
编写 Azure 感知自定义插件
注册和部署插件
处理插件中的异常
示例:创建基本插件
示例:从沙盒插件进行 Web 访问
运行代码生成工具
博客:使用插件修改视图

Microsoft Dynamics 365

© 2017 Microsoft。 保留所有权利。 版权