CRM插件实现:任务标记为完成后更新任务记录的问题
CRM Task标记完成后字段更新的Plugin实现问题与解决
问题描述
- 需求:用户点击「Mark as Complete」将Task的记录状态改为complete时,触发自定义逻辑并更新Task的部分字段
- 实现思路:因无专门的complete事件,选择在Update消息中通过Plugin检查状态变更
- 遇到的问题:
- 直接修改PostEntityImages时,CRM返回错误:
The object cannot be updated because it is read-only. If you contact support, please provide the technical details. - 使用PreEntityImages可更新字段,但无法获取变更后的
statuscode和modifiedon - 使用InputParameters中的Target仅能完成状态变更,自定义逻辑未触发
- 直接修改PostEntityImages时,CRM返回错误:
原核心代码片段:
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { currentTask = (Entity)context.InputParameters["Target"]; if (currentTask.LogicalName == "task") { afterUpdateTask = (Entity)context.PostEntityImages["updatedTask"]; beforeUpdateTask = (Entity)context.PreEntityImages["updatedTask"]; if (afterUpdateTask.Contains("statuscode")) { int statuscode = ((OptionSetValue)afterUpdateTask["statuscode"]).Value; if (statuscode == 5) { // 自定义逻辑与字段更新代码 } } } }
解决方案
可以通过Plugin实现,核心是不能直接修改Post/Pre实体图像,需通过OrganizationService重新发起更新操作,步骤如下:
1. 正确注册Plugin
- 消息:Update
- 实体:Task
- 事件管道阶段:Post Operation(同步模式)
- 勾选Pre Entity Image和Post Entity Image,图像名称统一设置(例如
TaskImage,需与代码中引用一致) - 筛选条件:可设置仅当
statuscode字段变更时触发,减少不必要执行
2. 修正后的核心代码
// 获取上下文与服务 IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); Entity preTask = null; Entity postTask = null; // 读取Pre和Post实体图像 if (context.PreEntityImages.Contains("TaskImage")) preTask = context.PreEntityImages["TaskImage"]; if (context.PostEntityImages.Contains("TaskImage")) postTask = context.PostEntityImages["TaskImage"]; // 验证状态变更:从非Complete变为Complete(statuscode=5) if (preTask != null && postTask != null) { int preStatus = ((OptionSetValue)preTask["statuscode"]).Value; int postStatus = ((OptionSetValue)postTask["statuscode"]).Value; // 仅当状态从非5变为5时触发逻辑 if (preStatus != 5 && postStatus == 5) { // 创建要更新的Task实体,仅携带需要修改的字段+Id Entity taskToUpdate = new Entity("task", postTask.Id); // 示例:更新自定义字段或系统字段 taskToUpdate["new_customfield"] = "标记完成后更新的内容"; taskToUpdate["description"] = $"任务于{postTask["modifiedon"]}完成"; // 使用Post中的modifiedon // 执行更新 service.Update(taskToUpdate); // 此处添加其他自定义逻辑(如关联记录操作、通知等) } }
关键说明
- PostEntityImages是只读的,仅用于读取变更后的字段值(如
statuscode、modifiedon),不能直接修改 - 必须通过
IOrganizationService发起新的Update请求来修改Task字段 - 添加状态变更的判断(
preStatus !=5 && postStatus==5),避免重复触发(例如Task已完成后再修改其他字段时不会重复执行逻辑)
内容的提问来源于stack exchange,提问作者Alireza Azadi
相关产品推荐
相关产品推荐

