You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dynamics CRM插件:新建Incident记录传值外部服务及字段更新问题

Dynamics 365插件:新建/更新Incident记录时的字段处理问题

问题1:新建记录时无法正确获取字段值

你遇到的第一个问题,本质是插件执行阶段和字段类型处理的问题,咱们一步步拆解:

为什么新建时直接用entity["X"]可能拿不到值?

当插件注册在Create消息的PreOperation阶段时,Target实体里只包含用户在表单上主动填写的字段,像createdon、ticketnumber这类系统自动生成的字段,还没写入数据库,所以直接从Target里拿不到。如果业务必须用到这些系统字段,要么把插件注册到PostOperation阶段,要么换个思路调整逻辑(不推荐Pre阶段先创建再查询,会多一次数据库操作)。

关于你碰到的Retrieve报错:Unable to cast object of type Microsoft.Xrm.Sdk.OptionSetValue to type Microsoft.Xrm.Sdk.EntityReference

这个错误很明确:你把一个**选项集字段(OptionSetValue)当成实体引用字段(EntityReference)**强转了。看你的代码,你写的是Owner = wholeCase.GetAttributeValue<EntityReference>("customerid").ToString();,但customerid是客户的实体引用,理论上不该是OptionSet。大概率是你写错了字段名(比如把某个状态字段误写成customerid),或者在ColumnSet里包含了其他OptionSet字段,却用EntityReference去获取。

不同类型字段的正确获取方式:

  • 文本/字符串字段:entity.GetAttributeValue<string>("subject")
  • 实体引用字段(比如customerid、ownerid):
    var customerRef = wholeCase.GetAttributeValue<EntityReference>("customerid");
    string owner = customerRef != null ? $"{customerRef.Name} ({customerRef.Id})" : string.Empty;
    
  • 日期时间字段(比如createdon):
    DateTime createTime = wholeCase.GetAttributeValue<DateTime>("createdon");
    string createTimeStr = createTime.ToString("yyyy-MM-dd HH:mm:ss"); // 转成你需要的格式
    
  • 选项集字段(比如statecode、statuscode):
    var stateOption = wholeCase.GetAttributeValue<OptionSetValue>("statecode");
    string states = stateOption != null ? stateOption.Value.ToString() : string.Empty;
    // 如果要获取选项集的显示名称,需要查询全局选项集或实体元数据
    

另外,新建记录时如果用PostOperation阶段,recordID = entity.Id是有效的,可以直接用这个ID去Retrieve完整实体。


问题2:更新记录时无法设置字段值

你说更新时用entity["X"] = "NewValue"不生效,核心要看插件注册的阶段:

  • 如果是PreOperation阶段:直接修改Target实体的属性是有效的,比如:
    entity["new_customfield"] = res.ToString();
    
    但要确保字段名拼写正确,且该字段具备可写权限。
  • 如果是PostOperation阶段:Target实体是只读的,这时候需要创建UpdateRequest来更新记录:
    Entity updateEntity = new Entity("incident", entity.Id);
    updateEntity["new_customfield"] = res.ToString();
    service.Update(updateEntity);
    

补充:如果插件注册在Create消息的Post阶段,要设置字段值的话,同样需要用UpdateRequest——因为此时Target已经是数据库里的记录,直接修改entity不会同步到数据库。


修正后的完整代码片段参考

IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);

if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
    try
    {
        var entity = (Entity)context.InputParameters["Target"];
        if (entity.LogicalName != "incident") 
            return;

        TicketViewModel ticket = new TicketViewModel();

        // 根据插件阶段处理字段获取
        if (context.MessageName == "Create" && context.Stage == 40) // PostOperation阶段
        {
            Guid recordID = entity.Id;
            ColumnSet cs = new ColumnSet("ticketnumber", "title", "description", "createdon", "customerid", "new_peygiriii", "createdby");
            Entity wholeCase = service.Retrieve("incident", recordID, cs);

            // 正确获取各字段值
            ticket.CaseID = wholeCase.GetAttributeValue<string>("ticketnumber");
            ticket.Subject = wholeCase.GetAttributeValue<string>("title");
            ticket.Description = wholeCase.GetAttributeValue<string>("description");
            
            DateTime createOn = wholeCase.GetAttributeValue<DateTime>("createdon");
            ticket.CreateTime = createOn.ToString("yyyy-MM-dd HH:mm:ss");

            var customerRef = wholeCase.GetAttributeValue<EntityReference>("customerid");
            ticket.Owner = customerRef != null ? customerRef.Name : string.Empty;

            var stateOption = wholeCase.GetAttributeValue<OptionSetValue>("statecode");
            ticket.States = stateOption != null ? stateOption.Value.ToString() : string.Empty;

            var assignedRef = wholeCase.GetAttributeValue<EntityReference>("createdby");
            ticket.Assigned = assignedRef != null ? assignedRef.Name : string.Empty;
        }
        else if (context.MessageName == "Create" && context.Stage == 20) // PreOperation阶段,只能拿用户填写的字段
        {
            ticket.Subject = entity.GetAttributeValue<string>("title");
            ticket.Description = entity.GetAttributeValue<string>("description");
            // 系统字段拿不到,需要调整业务逻辑或者换阶段
        }

        // 调用Web服务
        BasicHttpBinding httpBinding = new BasicHttpBinding();
        httpBinding.Name = "HttpBinding_Service";
        httpBinding.Security.Mode = BasicHttpSecurityMode.None;
        httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
        httpBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
        httpBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
        EndpointAddress epa = new EndpointAddress(@"webservice/url/address");
        CallChamberPortalSoapClient tcClient = new CallChamberPortalSoapClient(httpBinding, epa);
        var res = tcClient.addTicket(ticket);

        // 设置字段值,分阶段处理
        if (context.Stage == 20) // PreOperation,直接修改Target
        {
            entity["new_resultfield"] = res.ToString();
        }
        else // PostOperation,用UpdateRequest
        {
            Entity updateEntity = new Entity("incident", entity.Id);
            updateEntity["new_resultfield"] = res.ToString();
            service.Update(updateEntity);
        }
    }
    catch (Exception ex)
    {
        throw new InvalidPluginExecutionException("Failed to register ticket by this error: " + ex.Message);
    }
}

内容的提问来源于stack exchange,提问作者Mehdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:08:14