Dynamics 365中開發和註冊插件介紹

我是微軟Dynamics 365 & Power Platform方面的工程師羅勇,也是2015年7月到2018年6月連續三年Dynamics CRM/Business Solutions方面的微軟最有價值專家(Microsoft MVP),歡迎關注我的微信公衆號 MSFTDynamics365erLuoYong ,回覆380或者20191124可方便獲取本文,同時可以在第一間得到我發佈的最新博文信息,follow me!

前面的博文講了些客戶端編程,但是對於重要的數據,一般需要服務器端再做一次校驗,常用的手段就是插件和實時工作流,今天我講一下插件,官方文檔請參考 Write a plug-in 和 Register a plug-in 等。

首先需要創建一個 .NET Framework 的 Class Library項目,記得 Framework選擇 .NET Framework 4.6.2 。當然,爲不同版本的Dynamics 365 Customer Engagement選擇的Framework不盡相同,請根據官方文檔說明,我這個示例是爲 V9.X 版本做的示例。

 

 

首先通過NuGet添加對Microsoft.CrmSdk.CoreAssemblies的引用,如下圖,當然也要選擇合適的版本。如果不能上網的話,就需要添加對 Microsoft.Xrm.Sdk.dll 和 Microsoft.Crm.Sdk.Proxy.dll 的引用。

 

 

一般我會刪除生成的Class1.cs文件,而是使用固定的命名方式來命名。比如我這個插件步驟將會註冊在ly_WorkOrder實體的Create消息的Pre階段,我就會新建一個 PreWorkOrderCreate.cs 的文件來撰寫業務邏輯,當然這個類必須繼承 Microsoft.Xrm.Sdk.IPlugin 接口,我使用的代碼如下:常見的是獲取組織服務和跟蹤服務,其中插件日誌的使用請參考我的博文:Dynamics CRM 2015/2016新特性之三十四:有了插件日誌,調試插件so easy! ,若要使用映像(Image),請參考我的博文:Dynamics 365 CE Update消息PostOperation階段Image的嘗試  和  Dynamics 365 CE在Pre Delete插件中應用Image 。記得若要拋出用戶可見可理解的異常文本,請使用throw new InvalidPluginExecutionException。

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

namespace PluginDemo
{
    public class PreWorkOrderCreate : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            //獲取日誌服務
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            //寫一些日誌,方便跟蹤
            tracingService.Trace($"Enter PreWorkOrderCreate on {DateTime.UtcNow.ToString()}");
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                //插件針對的當前實體記錄,對於Pre Create來講,該對象包括了所有設置的字段值,若字段沒有設置值,在該對象中會不存在
                Entity currentEntity = (Entity)context.InputParameters["Target"];
                //獲取組織服務
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService orgSvc = serviceFactory.CreateOrganizationService(context.UserId);
                int provinceValue = Int32.MaxValue;
                int cityValue = Int32.MaxValue;
                string buName = string.Empty;
                //首先獲取要做校驗的值
                //記得先確認該屬性存在值再獲取其值,否則容易引發異常
                if (currentEntity.Contains("ly_province"))
                {
                    provinceValue = currentEntity.GetAttributeValue<OptionSetValue>("ly_province").Value;
                }
                if (currentEntity.Contains("ly_city"))
                {
                    cityValue = currentEntity.GetAttributeValue<OptionSetValue>("ly_city").Value;
                }
                var userEntity = orgSvc.Retrieve("systemuser", context.UserId, new ColumnSet("businessunitid"));
                //每個系統用戶肯定都設置了業務部門,我這裏只是例行檢查這個字段存在值
                if (userEntity.Contains("businessunitid"))
                {
                    buName = userEntity.GetAttributeValue<EntityReference>("businessunitid").Name;
                    if(buName == "Demo")
                    {
                        //省份字段用戶選擇了值才校驗
                        if(provinceValue != Int32.MaxValue)
                        {
                            if(provinceValue != 430000)
                            {
                                throw new InvalidPluginExecutionException($"省份字段值選擇有誤!");
                            }
                            else
                            {
                                //城市字段用戶選擇了值才做校驗
                                if(cityValue != Int32.MaxValue)
                                {
                                    if (cityValue >= provinceValue && cityValue < provinceValue + 10000)
                                    {
                                        tracingService.Trace($"城市字段選擇了值,且屬於正確的省份!");
                                    }
                                    else
                                    {
                                        throw new InvalidPluginExecutionException($"城市字段值選擇有誤!");
                                    }
                                }
                            }
                        }
                    }
                    else if(buName == "Sub Unit")
                    {
                        //省份字段用戶選擇了值才校驗
                        if (provinceValue != Int32.MaxValue)
                        {
                            if (provinceValue != 440000)
                            {
                                throw new InvalidPluginExecutionException($"省份字段值選擇有誤!");
                            }
                            else
                            {
                                //城市字段用戶選擇了值才做校驗
                                if (cityValue != Int32.MaxValue)
                                {
                                    if (cityValue >= provinceValue && cityValue < provinceValue + 10000)
                                    {
                                        tracingService.Trace($"城市字段選擇了值,且屬於正確的省份!");
                                    }
                                    else
                                    {
                                        throw new InvalidPluginExecutionException($"城市字段值選擇有誤!");
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    throw new InvalidPluginExecutionException($"系統異常,當前用戶(userid={context.UserId})的業務部門沒有設置!");
                }
            }
            tracingService.Trace($"Leave PreWorkOrderCreate on {DateTime.UtcNow.ToString()}");
        }
    }
}

 

記得一定要給該插件/自定義工作流活動程序集簽名,在Visual Studio中右擊該項目,選擇屬性(Properties) >  簽名(Signing),選中 Sign the assembly,我這裏新建一個Key file。

 

 

Key file我的設置如下,爲了簡便,我就不設置密碼保護了,保存後編譯插件項目,確定沒有編譯錯誤。

 

 

然後需要使用插件註冊工具將其註冊到Dynamics 365中,工具的下載請參考我的博文 下載Dynamics 365 Customer Engagement 工具 。雙擊其中的 PluginRegistration\PluginRegistration.exe 文件。點擊【CREATE NEW CONNECTION】,以便連接到Dynamics 365,下面這個截圖是連接到我自己的做了面向互聯網部署(IFD)的環境示例。

 

 

如果是連接到Dynamics 365 Customer Engagement Online,請參考下圖:

 

 

點擊【Register】 > 【Register New Assembly】。

 

 

 

選擇前面步驟編譯生成的插件程序集,Isolation Mode一般建議選擇Sandbox,而且Dynamics Customer Engagement Onine也只能選擇Sandbox,強烈建議選擇存儲到Database,點擊【Register Selected Plugins】按鈕,如果看不到該按鈕,是你的電腦分辨率太低所致,就用Tab鍵盤來輔助操作吧。

 

 

如果沒有錯誤的話會彈出類似如下對話框:

 

 

還需要右擊創建的Plugin,選擇【Register New Step】按鈕。

 

 

我這裏設置如下,是註冊在lw_workorder的Create消息的PreOperation階段,其餘的就不一一解釋了,請參考官方文檔,點擊【Register New Step】按鈕。

 

 

註冊成功後可以看到最終的結果類似如下:

 

 

剩下的工作就是測試了,使用InvalidPluginExecutionException拋出的異常信息在界面顯示效果如下:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章