Dynamic CRM 2013學習筆記(二)插件基本用法及調試


 

插件是可與 Microsoft Dynamics CRM 2013 和 Microsoft Dynamics CRM Online 集成的自定義業務邏輯(代碼),用於修改或增加平台的標准行為。也可以將插件認為是針對 Microsoft Dynamics CRM 觸發的事件的處理程序。您可以讓插件訂閱或注冊已知事件集,以便在事件發生時運行您的代碼。

 

一、基本用法

1. 要繼承IPlugin,並實現Excute方法 ( 1- 3 行)

2. 從service provide 里獲取執行上下文 ( 5行 )

3. 我們可以檢查觸發插件的實體名稱 ( 7 – 11 行)

4. 還可以檢查觸發的事件,是create, update 還是delete (12 – 16行 )

5. 輸入參數里獲取觸發的實體 ( 20 行 )

6. 通過service factory獲取IOrganizationService,當CreateOrganizationService方法的參數為null時,表示的是系統用戶,當參數為context.UserId 或Guid.Empty時,表示的是當前用戶 ( 21 – 23行)

7. 最后是DoAction方法,插件的邏輯就可以在這里實現了。

public class new_marketing_plan_updatePost : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
 
        //檢查實體名稱
        if (context.PrimaryEntityName.ToLower() != "new_marketing_plan")
        {
            throw new InvalidPluginExecutionException("Entity is not Marketing Plan");
        }
        // 檢查消息是否正確
        if (context.MessageName.ToLower() != "update")
        {
            throw new InvalidPluginExecutionException("message is not Update");
        }
 
        if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
        {
            Entity entity = (Entity)context.InputParameters["Target"];
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService userService = serviceFactory.CreateOrganizationService(context.UserId);
            IOrganizationService adminSerivce = serviceFactory.CreateOrganizationService(null);
 
            DoAction(adminSerivce, userService, entity);
        }
    }

 

二、刪除插件

根據上面的介紹,獲取當前實體的時是用的這種方式:

   Entity entity = (Entity)context.InputParameters["Target"];

但是對於刪除事件,就不能這樣獲取了,這時應該通過下面的方式來獲取:

  EntityReference er = context.InputParameters["Target"] as EntityReference;
  CurrentEntity = new Entity(er.LogicalName);
  CurrentEntity.Id = er.Id;
第一次寫刪除的插件,這個問題困擾了我好長時間。
 

三、用Unit Test調試插件

1. 下載Rhino.Mocks

2. 添加引用到unit test項目

Microsoft.Crm.sdk.proxy

Microsoft.Xrm.Client

Microsoft.Xrm.Sdk

Rhino.Mocks

System.Runtime.Serialization

以及要調試的項目,這里是MarketingManage

image

Rhino.Mocks.dll  下載 訪問密碼 4826

3. 初始化unit test

這里,我們用Rhino.Mocks來模擬IServiceProvider, IPluginExecutionContext, IOrganizationServiceFactory, IOrganizationService等變量。

(1)獲取CRM連接 ( 12 – 14 行 )

(2)用Rhino.Mocks來模擬IServiceProvider, IPluginExecutionContext, IOrganizationServiceFactory, IOrganizationService ( 16 – 20 行 )

public IServiceProvider serviceProvider;
         public IPluginExecutionContext context;
         public IOrganizationServiceFactory factory;
         public IOrganizationService service;
         public String prefix = "new_";
         public String customEntityName;
 
         [TestInitialize]
         public void GetOrgService()
         {
             //跨域調試采用這個URL,同域用http://me-crm-01/crm即可
             string server = "Url=http://crmdev:5555/CRM;Domain=xxx;Username=crmtest02;Password=abc-123";
 
             var myConnection = CrmConnection.Parse(server);
 
             serviceProvider = MockRepository.GenerateMock<IServiceProvider>();
             context = MockRepository.GenerateMock<IPluginExecutionContext>();
             factory = MockRepository.GenerateMock<IOrganizationServiceFactory>();
             service = MockRepository.GenerateMock<IOrganizationService>();
             service = new OrganizationService(myConnection);
         }

 

4. 調試

下面就進入調試方法了:

(1)模擬一個Entity當作觸發插件的實體 (4- 13行 )

(2)直接調試插件里的DoAction方法 (15-16 行 )

[TestMethod]
 public void TestApproePaymentrequest()
 {
     ParameterCollection paramBag = new ParameterCollection();
 
     XRMHelper helper = new XRMHelper(service);
     Entity currentent = helper.GetInfoByAttrValue("new_marketing_plan", "new_name", "20140910-000004")[0];  
     paramBag.Add("Target", currentent);
 
     context.Stub(x => x.InputParameters).Return(paramBag);
     serviceProvider.Stub(x => x.GetService(typeof(IPluginExecutionContext))).Return(context);
     serviceProvider.Stub(x => x.GetService(typeof(IOrganizationServiceFactory))).Return(factory);
     factory.Stub(x => x.CreateOrganizationService(null)).Return(service);
 
     new_marketing_plan_updatePost mp = new new_marketing_plan_updatePost();
     mp.DoAction(service, service, currentent);
 }
 

四、 日志記錄和跟蹤

有時插件寫好了,Unit Test也通過了,但注冊完插件,在真實環境里運行時,還是報錯,比如像Dynamic CRM 2013學習筆記(-)插件輸入實體參數解析里遇到的錯誤,這時我們就要用到跟蹤功能。

跟蹤功能可以提供運行時插件信息,以幫助診斷插件故障的原因,從而幫助開發人員解決插件問題。

此處所說的跟蹤不同於 ASP.NET 跟蹤。跟蹤是在 Microsoft Dynamics CRM SDK 中通過使用跟蹤服務 ITracingService 而實施的。開發人員在插件代碼中添加 Trace 語句,然后構建並部署插件。在執行過程中,只有當插件在運行時向平台傳回異常時,用戶才會看到跟蹤信息。對於同步注冊插件,跟蹤信息會顯示在 Microsoft Dynamics CRM Web 應用程序的對話框中。對於異步注冊插件,跟蹤信息會顯示在 Web 應用程序中“系統作業”窗體的“詳細信息”區域中。此類信息的數量和特點將取決於開發人員為插件編寫的代碼。

實施此類型跟蹤的主要原因是為了支持 Microsoft Dynamics CRM 中的隔離(沙盒)插件和自定義工作流活動功能。沙盒自定義代碼無法將信息寫入到系統事件日志或文件系統中。通過實施跟蹤服務,就為沙盒插件和自定義工作流活動提供了一種在拋出異常時輸出運行時信息的方法。此外,非沙盒插件也支持跟蹤功能。

用法:

(1) 初始化

 ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
(2) 添加Trace語句
  tracingService.Trace("In DoAction method");
 
實際上,我們可以在每個方法里try catch一下,這下可以快速定位到是哪個方法報錯,再通過Trace語句來精確定位。
例如:
               catch (Exception ex)
               {
                  throw new InvalidPluginExecutionException("GetQueryExpression error : " + ex.Message);
              }
下面是我的一個真實的case:
image 


Dynamic CRM 2013學習筆記 系列匯總


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM