【发布时间】: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