2

我正在尝试进行一项将地址从潜在客户迁移到联系人的活动。我们在 CRM 部署中不使用默认地址 1 和地址 2(不是我的决定),因此尽管资格认证过程确实将在线索中输入的地址复制到联系人,但它使用地址 1 字段这样做。我正在使用下面的代码,一切似乎都正常(没有错误注册,没有错误运行使用此活动的工作流)。只有一个问题……什么都没有发生。虽然没有错误,但没有创建地址。我以 CRM 管理员的身份运行,所以这不应该是权限问题,但是即使它不应该产生安全异常?任何想法为什么这不起作用?

public class MigrateLeadAddressToContactActivity : CodeActivity
{
    [Input("Contact input")]
    [ReferenceTarget("contact")]
    public InArgument<EntityReference> InContact { get; set; }

    protected override void Execute(CodeActivityContext executionContext)
    {
        // Get the tracing service                         
        var tracingService = executionContext.GetExtension<ITracingService>();

        if (InContact == null)
        {
            const string errorMessage = "Contact was not set for Address Migration Activity";
            tracingService.Trace(errorMessage);
            throw new InvalidOperationException(errorMessage);
        }

        // Get the context service.                         
        var context = executionContext.GetExtension<IWorkflowContext>();
        var serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();

        // Use the context service to create an instance of CrmService.             
        var service = serviceFactory.CreateOrganizationService(context.UserId);

        //Retrieve the contact id
        var contactId = this.InContact.Get(executionContext).Id;

        // Get The Lead if it exists
        var query = new QueryByAttribute
                    {
                        ColumnSet = new ColumnSet(
                            new[]
                            {
                                "address1_line1",
                                "address1_line2",
                                "address1_line3",
                                "address1_city",
                                "address1_stateorprovince",
                                "address1_postalcode",
                                "address1_country",
                            }
                        ),
                        EntityName = "lead"
                    };

        // The query will retrieve all leads whose associated contact has the desired ContactId
        query.AddAttributeValue("customerid", contactId); 

        // Execute the retrieval.
        var results = service.RetrieveMultiple(query);

        var theLead = results.Entities.FirstOrDefault();
        if (null == theLead)
        {
            tracingService.Trace("Activity exiting... Contact not sourced from Lead.");
            return;
        }

        var newAddress = new Entity("customeraddress");
        newAddress.Attributes["name"] = "business";
        newAddress.Attributes["objecttypecode"] = "contact";
        newAddress.Attributes["addresstypecode"] = 200000;
        newAddress.Attributes["parentid"] = new CrmEntityReference("contact", contactId);
        newAddress.Attributes["line1"] = theLead.Attributes["address1_line1"];
        newAddress.Attributes["line2"] = theLead.Attributes["address1_line2"];
        newAddress.Attributes["line3"] = theLead.Attributes["address1_line3"];
        newAddress.Attributes["city"] = theLead.Attributes["address1_city"];
        newAddress.Attributes["stateorprovince"] = theLead.Attributes["address1_stateorprovince"];
        newAddress.Attributes["postalcode"] = theLead.Attributes["address1_postalcode"];
        newAddress.Attributes["country"] = theLead.Attributes["address1_country"];

        service.Create(newAddress);
        tracingService.Trace("Address Migrated from Contact to Lead.");
    }
4

6 回答 6

0

一切对我来说都是正确的。如果没有找到线索,我会尝试抛出异常,只是为了验证您的查询是否正常工作。如果您没有收到异常,请确认您在创建客户地址时没有任何插件,这可能导致无法创建它。

于 2013-03-05T19:21:20.043 回答
0

假设确实没有抛出异常,那段代码的唯一其他出口就在这里

if (null == theLead)
{
    tracingService.Trace("Activity exiting... Contact not sourced from Lead.");
    return;
}

因此,假设theLead此时它为 null 并且工作流程优雅地结束是公平的。

要对此进行测试,请改为抛出异常。假设异常是 throwm,您可以调查它为什么为空。据推测,您过滤的值无效或不是您所期望的 - 或者该字段为空。

于 2013-03-05T19:47:41.680 回答
0

尝试从 Service.Create 追踪返回的 GUID 并查看其中包含的内容。

就像是:

Guid addressId = service.Create(newAddress);
tracingService.Trace(string.format("Address ID Result: {0}", addressId));
于 2013-03-05T21:38:58.983 回答
0

您似乎正在尝试直接创建地址记录,绕过默认情况下已经为联系人记录创建的两个记录(它总是创建这两个记录,无论您是否使用它们以及是否想要它们的“影子”字段在联系表格中可见)。您说什么都没发生 - 是否通过查看 SQL 表或联系人记录中的“更多地址”链接来验证?

您似乎从创建中省略的一件事是指定地址编号(理想情况下,首先找到已与联系人关联的所有地址上的最大数字并递增 1)。在所有情况下,这至少需要为 3。

如果您查看地址实体关联视图定义,您将看到它显式过滤以包含地址编号 > 2 的地址,以提供 1 和 2 是联系人“​​一部分”而“更多”是单独记录的错觉, 而实际上包括 1 和 2 在内的所有地址本身就是地址实体表中的行。

所以我怀疑如果将该值保留为空,则该地址根本不会显示在 GUI 中,因为它不符合过滤条件。它可能会也可能不会创建失败,因为它在内部非常依赖该字段,因此我会将其视为“系统必需”并确保将其包含在列集合中。

替代方法:

如果您从未在表单上使用 Add_1 或 Add_2 字段,您仍然可以使用地址编号为 2 的地址记录来存储来自潜在客户的数据,使其成为此现有(空)记录的更新而不是创建。

修改 Address Associated 视图以更改过滤器,使其在视图中包含 Add_2,方法是使其过滤地址编号 > 1 而不是 2。

这对用户来说似乎已经存在一个地址,并且他们可以使用 address_3、4 等(他们可能认为是 2、3 等)的正常功能添加更多地址。地址 1 存在但为空,可以忽略。

于 2013-03-06T11:22:30.840 回答
0

啊! 我现在看到您正在向后进行查询!(或者说你根本不需要查询)

客户 ID 字段仅在用户指定这是现有客户的潜在客户时使用,目的是创建与该客户链接的商机。

如果您确定潜在客户资格并创建联系人(和/或客户和/或机会),则将它们连接在一起的字段位于新创建的记录上,并且在所有三个实体的所有三种情况下都称为“originatingleadid”。请注意,这支持多次对领先者进行排位赛、取消排位赛和重新排位赛,并且通过这样做创建的每条记录都知道它的来源(想想“谁是你的爸爸?”你不会忘记这一点!)。

如果关系相反,领导者只能记住其中的最后一个。

因此,要修复代码的查询部分,请替换查询并从您正在处理的联系人的查找字段中显式获取 originatingleadid。

我的另一个答案仍然是使用更新而不是创建来处理整个过程的更好方法,但是这个答案应该让您首先使用正确的潜在客户记录。

于 2013-03-06T11:29:45.183 回答
0

如果此代码是为 CRM 2011 编写的(看起来确实如此),那么您需要使用 OptionSetValue 对象而不是整数来设置 addresstypecode 值:

newAddress.Attributes["addresstypecode"] = 200000; 

变成

newAddress.Attributes["addresstypecode"] = new OptionSetValue(200000);

我实际上希望这会引发异常。我不确定为什么不是。

于 2013-10-02T16:03:41.507 回答