更新 我从该论坛以及Dynamics论坛中获取了一些信息,并且我的代码可以正常工作。代码中的主要问题是我只查看了preImage,但是在大多数情况下,这三个值之一将被更新,这意味着我无法针对该特定字段的preImage。我更改了逻辑以使用Collection属性(更新值)(如果已更新),但是使用PreImage值(如果未更新)-这使代码起作用,并且每次都会触发更新-不再需要触发插件两次!这是更新后的代码-比原始代码更有效,更简洁(向下滚动以查看旧的/无效的代码)。我还添加了一些评论,以使其更易于理解。感谢所有人的帮助(在SO和Dynamics论坛上都是如此!)
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace CLIENTNTE
{
public class NTEExceedance : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
Decimal nte_percent = 0;
Decimal subtotalDecimal = 0;
Decimal nteDecimal = 0;
Decimal amountDiffDecimal = 0;
Decimal percentDifference = 0;
try
{
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
//if entity is not Work Order, return. Prevents plugin firing on wrong entity (in case of wrong registration in plugin registration tool)
if (entity.LogicalName != "msdyn_workorder")
{
return;
}
//get preimage of WO Entity
Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
//logic for when updated attribute is NTE Amount
if (entity.Attributes.Contains("CLIENT_nteamount") == true)
{
nteDecimal = entity.GetAttributeValue<Money>("CLIENT_nteamount").Value;
}
else
{
nteDecimal = preMessageImage.GetAttributeValue<Money>("CLIENT_nteamount").Value;
}
//logic for when updated attribute is NTE Percent
if (entity.Attributes.Contains("CLIENT_ntepercent") == true)
{
nte_percent = entity.GetAttributeValue<Decimal>("CLIENT_ntepercent");
}
else
{
nte_percent = preMessageImage.GetAttributeValue<Decimal>("CLIENT_ntepercent");
}
//logic for when updated attribute is Estimate Subtotal Amount
if (entity.Attributes.Contains("msdyn_estimatesubtotalamount") == true)
{
subtotalDecimal = entity.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
}
else
{
subtotalDecimal = preMessageImage.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
}
//calculation of Amount Difference, and Percent Difference
amountDiffDecimal = (subtotalDecimal - nteDecimal);
percentDifference = ((amountDiffDecimal / nteDecimal) * 100);
//Comparison logic to update the NTE Exceeded flag
if (percentDifference > nte_percent)
{
entity["CLIENT_nteexceeded"] = true;
}
if (percentDifference <= nte_percent)
{
entity["CLIENT_nteexceeded"] = false;
}
}
}
catch (FaultException<OrganizationServiceFault> e)
{
//write errors to the CRM Plugin Trace Log
tracingService.Trace("CLIENTPlugin - Update NTEExceededNonCalc: {0}", e.ToString());
//Throw error through UI
throw new InvalidPluginExecutionException("Error, Please See Plugin Log");
}
}
}
}
原始帖子 再回来吧!昨天,我意识到我不使用PreImage来获取未包含在更新的属性集合中的值的错误-SCORE!现在,插件可以工作,但仅在我触发插件时每隔一次就可以工作。
因此,似乎插件实际上正在启动(我可以在“设置”>“插件配置文件”中看到插件配置文件),但是没有执行我需要的更新,直到第二次触发插件为止。这似乎发生在我正在监听的所有3个属性上,并且每个属性都需要更新两次(例如,如果我更新了属性1,则插件不会更新我的值,如果我随后更新了属性2,插件仍然不会更新我的值,直到再次重新更新属性1或属性2为止)。在我分析/调试代码并逐步执行代码时,我可以看到if语句被命中,并且更新了实体字段的代码行也正在执行-但由于某种原因,它没有设置值( CLIENT_nteexceeded = true或false),直到我第二次触发它为止。如果它根本不更新实体记录值,那将更有意义,而且我缺少某种类型的“更新”消息(我曾使用过service.Entity.Update(),但似乎没有应用于此插件)
我对CRMDEV还是一个新手,所以请原谅这个愚蠢的问题。对我来说,这似乎是一个非常愚蠢的问题,这肯定是我所缺少的小事情。关于为什么这迫使我两次触发代码以执行更新的任何想法?
这是插件步骤的配置。这三个过滤器属性是代码中引用的属性。同样,插件工作正常,只是不会每次都更新记录。
下面的代码(删除了对客户名称的引用)
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace CLIENTNTE
{
public class NTEExceedance : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
//Extract the tracing service for use in debugging sandboxed plug-ins.
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
Money subtotal = null;
Money nte = null;
Decimal nte_percent = 0;
Decimal subtotalDecimal = 0;
Decimal nteDecimal = 0;
Decimal amountDiffDecimal = 0;
Decimal percentDifference = 0;
try
{
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName == "msdyn_workorder")
{
//code fires onChange of NTE Amount (same logic will apply to NTE % and Est Subtotal Amount)
if (entity.Attributes.Contains("CLIENT_nteamount") == true)
{
//String NewValue = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()));
// String NewSubTotal = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()), entity["msdyn_estimatesubtotalamount"].ToString());
//String NewNTE = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()), entity["CLIENT_nteamount"].ToString());
//String Newpercent = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()), entity["CLIENT_ntepercent"].ToString());
if (context.PreEntityImages.Contains("WONTEPreImage") && context.PreEntityImages["WONTEPreImage"] is Entity)
{
Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
// get topic field value before database update perform
//pretopic = (String)preMessageImage.Attributes["subject"];
subtotal = (Money)preMessageImage.Attributes["msdyn_estimatesubtotalamount"];
nte = (Money)preMessageImage.Attributes["CLIENT_nteamount"];
nte_percent = (Decimal)preMessageImage.Attributes["CLIENT_ntepercent"];
}
//old way of trying to get values NON IMAGE
//subtotal = (Money)entity.Attributes["msdyn_estimatesubtotalamount"];
//nte = (Money)entity.Attributes["CLIENT_nteamount"];
//nte_percent = (Decimal)entity.Attributes["CLIENT_ntepercent"];
subtotalDecimal = subtotal.Value;
nteDecimal = nte.Value;
amountDiffDecimal = (subtotalDecimal - nteDecimal);
percentDifference = ((amountDiffDecimal / nteDecimal) * 100);
if (percentDifference > nte_percent)
{
//know this snippet works
entity["CLIENT_nteexceeded"] = true;
}
if (percentDifference <= nte_percent)
{
//know this snippet works
entity["CLIENT_nteexceeded"] = false;
}
}
if (entity.Attributes.Contains("CLIENT_ntepercent") == true)
{
if (context.PreEntityImages.Contains("WONTEPreImage") && context.PreEntityImages["WONTEPreImage"] is Entity)
{
Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
// get topic field value before database update perform
//pretopic = (String)preMessageImage.Attributes["subject"];
subtotal = (Money)preMessageImage.Attributes["msdyn_estimatesubtotalamount"];
nte = (Money)preMessageImage.Attributes["CLIENT_nteamount"];
nte_percent = (Decimal)preMessageImage.Attributes["CLIENT_ntepercent"];
}
//old way of trying to get values NON IMAGE
//subtotal = (Money)entity.Attributes["msdyn_estimatesubtotalamount"];
//nte = (Money)entity.Attributes["CLIENT_nteamount"];
//nte_percent = (Decimal)entity.Attributes["CLIENT_ntepercent"];
subtotalDecimal = subtotal.Value;
nteDecimal = nte.Value;
amountDiffDecimal = (subtotalDecimal - nteDecimal);
percentDifference = ((amountDiffDecimal / nteDecimal) * 100);
if (percentDifference > nte_percent)
{
//know this snippet works
entity["CLIENT_nteexceeded"] = true;
}
if (percentDifference <= nte_percent)
{
//know this snippet works
entity["CLIENT_nteexceeded"] = false;
}
}
if (entity.Attributes.Contains("msdyn_estimatesubtotalamount") == true)
{
if (context.PreEntityImages.Contains("WONTEPreImage") && context.PreEntityImages["WONTEPreImage"] is Entity)
{
Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
subtotal = (Money)preMessageImage.Attributes["msdyn_estimatesubtotalamount"];
nte = (Money)preMessageImage.Attributes["CLIENT_nteamount"];
nte_percent = (Decimal)preMessageImage.Attributes["CLIENT_ntepercent"];
}
//old way of trying to get values NON IMAGE
//subtotal = (Money)entity.Attributes["msdyn_estimatesubtotalamount"];
//nte = (Money)entity.Attributes["CLIENT_nteamount"];
//nte_percent = (Decimal)entity.Attributes["CLIENT_ntepercent"];
subtotalDecimal = subtotal.Value;
nteDecimal = nte.Value;
amountDiffDecimal = (subtotalDecimal - nteDecimal);
percentDifference = ((amountDiffDecimal / nteDecimal) * 100);
if (percentDifference > nte_percent)
{
//know this snippet works
entity["CLIENT_nteexceeded"] = true;
}
if (percentDifference <= nte_percent)
{
//know this snippet works
entity["CLIENT_nteexceeded"] = false;
}
}
}
}
}
catch (FaultException<OrganizationServiceFault> e)
{
tracingService.Trace("CLIENTPlugin - Update NTEExceededNonCalc: {0}", e.ToString());
throw e;
}
}
}
}
答案 0 :(得分:1)
我将帮助您了解CRM执行管道的工作方式。然后,您可以借助trace / Audit / profiler进行故障排除,以找出失败的地方。
基本上,您是在预验证/预操作阶段中,在数据库事务处理之前,截获CRM CRM中发生的service.Update()
平台调用。然后根据业务需要进行数据处理,并在目标实体本身中设置额外的属性值。这避免了另一个显式的额外service.Update()
调用和返回循环死锁。
如果有任何异常,则表示您正在登录跟踪并抛出该异常。我建议将其更改为InvalidPluginExecutionException
,您将在UI弹出窗口中看到它。这将回滚事务,这意味着将不会保存数据。
此外,为了更好地理解-记录每个条件语句,变量值等,以查看发生问题的确切跟踪日志。
答案 1 :(得分:1)
更新/答案我从该论坛以及Dynamics论坛中获取了一些信息,并且我的代码可以正常工作。代码中的主要问题是我只查看了preImage,但是在大多数情况下,这三个值之一将被更新,这意味着我无法针对该特定字段的preImage。我更改了逻辑以使用Collection属性(更新值)(如果已更新),但是使用PreImage值(如果未更新)-这使代码起作用,并且每次都会触发更新-不再需要触发插件两次!这是更新后的代码-比原始代码更有效,更简洁(向下滚动以查看旧的/无效的代码)。我还添加了一些评论,以使其更易于理解。感谢所有人的帮助(在SO和Dynamics论坛上都是如此!)
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace CLIENTNTE
{
public class NTEExceedance : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
Decimal nte_percent = 0;
Decimal subtotalDecimal = 0;
Decimal nteDecimal = 0;
Decimal amountDiffDecimal = 0;
Decimal percentDifference = 0;
try
{
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
//if entity is not Work Order, return. Prevents plugin firing on wrong entity (in case of wrong registration in plugin registration tool)
if (entity.LogicalName != "msdyn_workorder")
{
return;
}
//get preimage of WO Entity
Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
//logic for when updated attribute is NTE Amount
if (entity.Attributes.Contains("CLIENT_nteamount") == true)
{
nteDecimal = entity.GetAttributeValue<Money>("CLIENT_nteamount").Value;
}
else
{
nteDecimal = preMessageImage.GetAttributeValue<Money>("CLIENT_nteamount").Value;
}
//logic for when updated attribute is NTE Percent
if (entity.Attributes.Contains("CLIENT_ntepercent") == true)
{
nte_percent = entity.GetAttributeValue<Decimal>("CLIENT_ntepercent");
}
else
{
nte_percent = preMessageImage.GetAttributeValue<Decimal>("CLIENT_ntepercent");
}
//logic for when updated attribute is Estimate Subtotal Amount
if (entity.Attributes.Contains("msdyn_estimatesubtotalamount") == true)
{
subtotalDecimal = entity.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
}
else
{
subtotalDecimal = preMessageImage.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
}
//calculation of Amount Difference, and Percent Difference
amountDiffDecimal = (subtotalDecimal - nteDecimal);
percentDifference = ((amountDiffDecimal / nteDecimal) * 100);
//Comparison logic to update the NTE Exceeded flag
if (percentDifference > nte_percent)
{
entity["CLIENT_nteexceeded"] = true;
}
if (percentDifference <= nte_percent)
{
entity["CLIENT_nteexceeded"] = false;
}
}
}
catch (FaultException<OrganizationServiceFault> e)
{
//write errors to the CRM Plugin Trace Log
tracingService.Trace("CLIENTPlugin - Update NTEExceededNonCalc: {0}", e.ToString());
//Throw error through UI
throw new InvalidPluginExecutionException("Error, Please See Plugin Log");
}
}
}
}