【问题标题】:Why is my update in my plugin on my custom entity not occurring?为什么我的自定义实体插件中的更新没有发生?
【发布时间】:2015-09-27 22:37:25
【问题描述】:

我正在为 MS Dynamics CRM 2015 编写一个自动编号插件。它可以在需要生成新编号时创建机会。当前编号存储在另一个实体中,该实体在创建机会时检索,然后加 1。然后使用新编号更新自动编号实体(除非它不是,因为目前这不起作用)。

此时检索到该数字并将其添加 1 并在机会中正确使用。但是,由于在创建另一个机会时不会更新自动编号实体,因此它会获得与前一个相同的编号。

到目前为止,这是我的插件代码:

protected void ExecuteGenerateOpportunityAutoNumber(LocalPluginContext localContext)
{
    if (localContext == null)
    {
        throw new ArgumentNullException("localContext");
    }

    IPluginExecutionContext context = localContext.PluginExecutionContext;
    IOrganizationService service = localContext.OrganizationService;

    if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
    {
        Entity entity = (Entity)context.InputParameters["Target"];

        if (entity.LogicalName == OPPORTUNITY_ENTITY_NAME)
        {
            if (!entity.Attributes.Contains(OPPORTUNITY_REF_ID))
            {
                try
                {
                    string newId = RetrieveAndUpdateLastId(service);
                    entity.Attributes.Add(OPPORTUNITY_REF_ID, newId);
                }
                catch (FaultException ex)
                {
                    throw new InvalidPluginExecutionException("GenerateOpportunityAutoNumber plugin error: ", ex);
                    //tracingService.Trace("GenerateOpportunityAutoNumber plugin error: {0}", ex.Message);
                }
            }
        }
    }
}

RetrieveAndUpdateLastId 方法代码如下:

private string RetrieveAndUpdateLastId(IOrganizationService service)
{
    lock (lastIdentifierLock)
    {
        string result = null;

        ColumnSet cols = new ColumnSet();
        cols.AddColumns(LAST_REF_LAST_VALUE, LAST_REF_PRIMARY_KEY);

        QueryExpression query = new QueryExpression();
        query.ColumnSet = cols;
        query.EntityName = LAST_REF_ENTITY_NAME;

        EntityCollection ec = service.RetrieveMultiple(query);

        if (ec.Entities.Count >= 1)
        {
            foreach (Entity identifier in ec.Entities)
            {
                if (identifier.Attributes.Contains(LAST_REF_LAST_VALUE))
                {
                    int? lastValue = identifier[LAST_REF_LAST_VALUE] as int?;
                    if (lastValue != null)
                    {
                        string newValue = (lastValue.Value + 1).ToString().PadLeft(7, '0');

                        result = String.Format("SN{0}", newValue); //This is clearly happening as I'm getting the next number back.

                        identifier[LAST_REF_LAST_VALUE] = lastValue.Value + 1;

                        //Tried this also:
                        //identifier.Attributes.Remove(LAST_REF_LAST_VALUE);
                        //identifier.Attributes.Add(LAST_REF_LAST_VALUE, lastValue.Value + 1);

                        service.Update(identifier); //This doesn't seem to be happening.
                        break;
                    }
                }
            }
        }
        return result;
    }
}

不会引发错误,但不会更新自动编号。我已经检查了我正在运行它的用户,因为它对自动编号实体也具有所需的更新权限。有什么想法吗?

更新

调试后我发现它抛出了一个错误,即 Principal 用户缺少 prvWrite 权限。这可以解释为什么没有更新,但现在又引发了另一个问题。我已将插件设置为作为特定用户(具有正确权限的用户)运行,但错误中“主要用户”的 Guid 是调用用户的。当我设置它使用特定用户时,为什么它会作为调用用户运行?

更新 2

我想我可能已经找到了这个问题,但想知道是否有其他人可以确认/对此有所了解。根据this 看来,问题可能在于用户不在特定的 AD 组中,具体而言

用户帐户 (A) 需要权限 prvActOnBehalfOfAnotherUser, 这包含在 Delegate 角色中。

或者,仅对于 Active Directory 目录服务部署, 运行模拟代码的用户帐户 (A) 可以是 添加到 Active Directory 中的 PrivUserGroup 组。这组是 由 Microsoft Dynamics CRM 在安装和设置期间创建。用户 帐户 (A) 不必与获得许可的 Microsoft 相关联 动态 CRM 用户。但是,被冒充的用户 (B) 必须是获得许可的 Microsoft Dynamics CRM 用户。

出于我的目的,我认为我尝试运行的用户需要在 AD 中的 PrivUserGroup 中(事实并非如此),否则它默认为调用用户。

更新 3

我已经能够确定 2 个基本问题。第一个如上所述,上下文始终作为调用用户运行。第二个是,当给调用用户系统管理员权限或使用空参数创建 IOrganizationService 时,它​​仍然不会更新。但是,这似乎很奇怪,这两种情况在分析插件时确实有效。为什么会这样?

更新 4

似乎我可能已经解决了这个问题,虽然我不确定(因此我还没有写一个答案)。根据文档,我们已将要模拟的用户添加到 PrivUserGroup 中。该插件现在可以工作了。但是,我不明白为什么需要这样做。另外,这是在这种情况下的最佳做法,还是我做了一些不应该做的事情?

在相关说明中,我这次在部署插件之前还取消了注册,所以我现在想知道这是否解决了这个问题。为了确认我现在已经从 AD 中的 PrivUserGroup 中删除了用户,但这显然需要一些时间(不确定到底多长时间)才能过滤。如果它仍然有效,那么看起来这实际上解决了它。您通常需要在重新部署插件之前取消注册插件以确保其正常工作吗?

更新 5

好的,如果我最后一次更新的话。我没有将此标记为答案,因为我不是 100% 确定,但似乎使用插件注册工具删除程序集可能已经成功了。从我读过的所有内容中,您不需要取消注册插件即可重新部署,所以我的程序集可能以某种方式损坏,通过删除它并使用新程序集再次创建它可以解决问题。不幸的是,我没有要测试的原始程序集。

【问题讨论】:

    标签: plugins dynamics-crm dynamics-crm-2015


    【解决方案1】:

    我建议调试您的插件。下面的文章包含一个视频,描述了如何使用 Plugin Debugger 和 Plugin Regitration Tool 调试插件 - http://blogs.msdn.com/b/devkeydet/archive/2015/02/17/debug-crm-online-plugins.aspx

    更新如何为用户上下文和系统提供 2 个 IOrganizationService 实例:

    1. 打开 Plugin.cs 文件。
    2. 找到以下代码:

      internal IOrganizationService OrganizationService
      {
          get;
      
          private set;
      }
      
    3. 在后面添加以下代码:

      internal IOrganizationService SystemOrganizationService
      {
          get;
      
          private set;
      }
      
    4. 找到以下代码:

          // Use the factory to generate the Organization Service.
          this.OrganizationService = factory.CreateOrganizationService(this.PluginExecutionContext.UserId);
      
    5. 在后面添加以下代码:

      this.SystemOrganizationService = factory.CreateOrganizationService(null);

    6. 在需要更高级别权限的地方使用此 IOrganizationService 实例。

    【讨论】:

    • 谢谢。我会试一试。我怀疑自动编号实体的设置方式有问题。也许它是不可更新的。
    • 我现在找到了问题的根源,但没有解决它。你能看看我的更新吗?
    • 你应该走其他路。不要尝试在其他用户的上下文中运行插件,而是尝试使用 null 参数而不是 UserId 来实例化 IOrganization。
    • 这有什么好处?为什么用 null UserId 实例化 IOrganization 服务会给我正确的权限?
    • null 参数将为您提供最高权限 - 系统级别,因此不会从权限等点阻止任何对 CRM 的调用
    猜你喜欢
    • 1970-01-01
    • 2022-11-11
    • 2022-10-05
    • 2018-02-21
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 2017-06-28
    • 2011-05-18
    相关资源
    最近更新 更多