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

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:Dynamic CRM 2013学习笔记 系列汇总
Dynamic CRM 2013学习笔记(二)插件基本用法及调试的更多相关文章
- Dynamic CRM 2013学习笔记(十二)实现子表合计(汇总,求和)功能的通用插件
上一篇 Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能 , 介绍了如何用js来实现子表合计功能,这种方法要求在各个表单上添加js方法,如果有很多 ...
- Dynamic CRM 2013学习笔记(二十二)插件里调用WCF服务
1. 添加service: 2.调用WCF BasicHttpBinding myBinding = new BasicHttpBinding(); myBinding.Name = &q ...
- Dynamic CRM 2013学习笔记(四)单据编号及插件批量注册工具
基本上每个实体form上都会有单据编号,而且不同的实体编号要求还不太一样,这时就需要一个通用的单据编号插件,可配置以应对不同的需求. 下面简单介绍下实现步骤: 1. 创建二个实体,以保存各实体所要求的 ...
- Dynamic CRM 2013学习笔记(二十)字段改变事件的二种实现方法
CRM里有二种方式实现字段change事件,一种是在form里,一种完全通过js来实现.本文介绍下二者的用途及区别. 1. Form里用法 这种方式估计其实也是添加一个js的function. 这种方 ...
- Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置
上次介绍了<Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示> 以及如何配置自定义审批流的按钮:<Dynamic CRM 2013学习笔记(二十一)自定义 ...
- Dynamic CRM 2013学习笔记(三十五)自定义审批流6 - 审批通过后,再审批 - 二次审批
最近有个特殊的需求,客户想做二次审批,就是审批通过后,再走一次审批流程.最开始一想,这还不简单,审批通过后,直接把状态改成draft就完了,后来一试,发现一堆问题,比如第一次审批完后,界面是不允许修改 ...
- Dynamic CRM 2013学习笔记(四十二)流程5 - 实时/同步工作流(Workflow)用法图解
实时工作流跟插件一样,也是用事件执行管道来执行,能在pre,post或核心操作中执行.跟插件一样,不能在创建之前和删除之后执行.如果执行过程中有异常发生,会取消并回滚整个操作.实时工作流里所有的活动和 ...
- Dynamic CRM 2013学习笔记(一)插件输入实体参数解析
1. 问题描述 最近新建了一个post事件的插件,传入的参数处理如下: 1: if (context.InputParameters.Contains("Target") &a ...
- Dynamic CRM 2013学习笔记(二十三)CRM JS智能提示(CRM 相关的方法、属性以及页面字段),及发布前调试
我们知道在CRM的js文件里引用XrmPageTemplate.js后,就可以实现智能提示,但每个js文件都引用太麻烦了,其实可以利用vs的功能让每个js文件自动实现智能提示CRM的js: 另外,我们 ...
随机推荐
- Find Query Window的运作(手电筒)
Find Query Window的運作?(手电筒) 提示: 在點選 Toolbar的 Find鈕時,系統會觸發 Query_Find此 Trigger. 執行 App_Find.Query_Find ...
- Mybatis保存数据时事务问题
今天不小心在sqlplus中用for update ,然后事务没提交,结果在项目中一直保存不进去数据,找了很久发现是sqlplus中的事务没提交,哎,这种问题真得避免啊,一定要细心啊!
- redis:hash 数据类型
简介 Redis Hashes是字符串字段和字符串值之间的映射,所以它们是完美的表示对象(eg:一个有名,姓,年龄等属性的用户)的数据类型.新建一个hash对象时开始是用zipmap(又称为small ...
- VC++ 关于 ON_UPDATE_COMMAND_UI 相关的作用.
ON_COMMAND_RANGE(ID_SORTING_GROUPBYTYPE, ID_SORTING_SORTBYACCESS, OnSort) ON_UPDATE_COMMAND_UI_RANGE ...
- redis3.0.5集群部署安装详细步骤
Redis集群部署文档(centos6系统) (要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下) ...
- Linux shell之sed
sed编辑器逐行处理输入,然后把结果发送到屏幕. -i选项:直接作用源文件,源文件将被修改. sed命令和选项: a\ 在当前行后添加一行或多行 c\ 用新文本替换当前行中的文本 d 删除行 i\ 在 ...
- git服务器的搭建
http://blog.jobbole.com/25944/ 1,概念 git服务器:就是一个仓储,一个大家都可以访问的公共仓储,大家可以从这个仓储中拉取和推送数据. 协议: 与gist服务通讯的仓储 ...
- C++中的预处理
一.预处理的由来: 在C++的历史发展中,有很多的语言特征(特别是语言的晦涩之处)来自于C语言,预处理就是其中的一个.C++从C语言那里把C语言预处理器继承过来(C语言预处理器,被Bjarn ...
- Android WebView 实现缓存网页数据
WebView中存在着两种缓存:网页数据缓存(存储打开过的页面及资源),H5缓存(即AppCache). 将我们浏览过的网页url已经网页文件(css.图片.js等)保存到数据库表中 缓存模式(5种) ...
- Dynamic CRM2016在一台本地服务器安装部署
在本地单独一台服务器上安装部署CRM2016时需要提前安装好CRM软件需要的必备软件,具体需要安装的组件如下截图:其中required为必须具备的安装组件.license可以采用微软官网的90天测试版 ...