简体   繁体   English

CRM 2011自定义工作流程

[英]CRM 2011 Custom Workflow

I GO THE PLUGIN WORKING, AND I HAVE UPDATED THE WORKING CODE HERE. 我进行了插件工作,并且这里更新了工作代码。 HOPE IT HELPS!! 希望能帮助到你!!

I'm creating a workflow which has a plugin to retrieve a contact entity from a "FROM" field of an Email record. 我正在创建一个工作流,该工作流的插件可以从电子邮件记录的“ FROM”字段中检索联系人实体。 I'm trying to see if that email exists in the contact entity. 我正在尝试查看联系人实体中是否存在该电子邮件。 The input is the "FROM" email and the output will return the Contacts entity. 输入是“ FROM”电子邮件,输出将返回Contacts实体。 I have not been able to get this code working, I've received different errors or no errors, but I know its not working. 我无法使此代码正常工作,我收到了其他错误或没有错误,但我知道它无法正常工作。 Please help! 请帮忙! Thanks in advance! 提前致谢!

using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;
using System;

namespace GetSenderPlugin
{
  public class GetSenderPlugin : CodeActivity
  {
    protected override void Execute(CodeActivityContext executionContext)
    {
        //Create the tracing service
        ITracingService trace = executionContext.GetExtension<ITracingService>();
        trace.Trace("*****Tracing Initiated*****");

        //Create the IWorkflowContext and the IOrganizationService for communication with CRM
        IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
        IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
        trace.Trace("*****IOrganizationService created*****");

        trace.Trace("*****Entity logical Name: " + Email.Get<EntityReference>(executionContext).LogicalName + "*****");
        trace.Trace("*****Entity ID: " + Email.Get<EntityReference>(executionContext).Id + "*****");

        if (Email != null && string.Compare(Email.Get<EntityReference>(executionContext).LogicalName, "email", false) == 0)
        {
            EntityReference retrieveEmail = new EntityReference();
            retrieveEmail.Id = Email.Get<EntityReference>(executionContext).Id;
            retrieveEmail.LogicalName = Email.Get<EntityReference>(executionContext).LogicalName;
            retrieveEmail.Name = Email.Get<EntityReference>(executionContext).Name;

            string[] strArrays = new string[1];
            strArrays[0] = "from";

            ColumnSet columnSet = new ColumnSet();
            columnSet.AddColumn(strArrays[0]);

            RetrieveRequest retrieveRequest = new RetrieveRequest();
            retrieveRequest.Target = retrieveEmail;
            retrieveRequest.ColumnSet = columnSet;
            trace.Trace("*****Retrieve Request declared*****");

            RetrieveResponse retrieveResponse = (RetrieveResponse)service.Execute(retrieveRequest);
            trace.Trace("*****Retrieve Response executed*****");

            Email businessEntity = (Email)retrieveResponse.Entity;
            trace.Trace("*****businessEnitity retrieved*****");

            //ActivityParty activitypartyArray = (ActivityParty)businessEntity.From.FirstOrDefault;
            foreach (ActivityParty activityParty in businessEntity.From)
            {
                trace.Trace("*****Activity Party Name: " + activityParty.PartyId.LogicalName + "*****");
                trace.Trace("*****Activity Party Id: " + activityParty.PartyId.Id + "*****");
                if (activityParty != null && activityParty != null && activityParty.PartyId != null)
                {
                    string str = activityParty.PartyId.LogicalName;
                    if (str.CompareTo("contact") != 0)
                    {
                        trace.Trace("*****Not Contact*****");
                        if (str.CompareTo("account") != 0)
                        {
                            trace.Trace("*****Not Account*****");
                            if (str.CompareTo("lead") != 0)
                            {
                                trace.Trace("*****Not Lead*****");
                                if (str.CompareTo("systemuser") != 0)
                                {
                                    trace.Trace("*****Not System User*****");
                                    if (str.CompareTo("queue") == 0)
                                    {
                                        Queue.Set(executionContext, activityParty.PartyId);
                                        Contact.Set(executionContext, new EntityReference("contact", Guid.NewGuid()));
                                        User.Set(executionContext, new EntityReference("systemuser", Guid.NewGuid()));
                                        Lead.Set(executionContext, new EntityReference("lead", Guid.NewGuid()));
                                        Account.Set(executionContext, new EntityReference("account", Guid.NewGuid()));
                                    }
                                    else
                                    {
                                        trace.Trace("*****User not found*****");
                                        Queue.Set(executionContext, new EntityReference("queue", Guid.NewGuid()));
                                        Contact.Set(executionContext, new EntityReference("contact", Guid.NewGuid()));
                                        User.Set(executionContext, new EntityReference("systemuser", Guid.NewGuid()));
                                        Lead.Set(executionContext, new EntityReference("lead", Guid.NewGuid()));
                                        Account.Set(executionContext, new EntityReference("account", Guid.NewGuid()));
                                    }
                                }
                                else
                                {
                                    User.Set(executionContext, activityParty.PartyId);
                                    Contact.Set(executionContext, new EntityReference("contact", Guid.NewGuid()));
                                    Queue.Set(executionContext, new EntityReference("queue", Guid.NewGuid()));
                                    Lead.Set(executionContext, new EntityReference("lead", Guid.NewGuid()));
                                    Account.Set(executionContext, new EntityReference("account", Guid.NewGuid()));
                                }
                            }
                            else
                            {
                                Lead.Set(executionContext, activityParty.PartyId);
                                Contact.Set(executionContext, new EntityReference("contact", Guid.NewGuid()));
                                Queue.Set(executionContext, new EntityReference("queue", Guid.NewGuid()));
                                User.Set(executionContext, new EntityReference("systemuser", Guid.NewGuid()));
                                Account.Set(executionContext, new EntityReference("account", Guid.NewGuid()));
                            }
                        }
                        else
                        {
                            Account.Set(executionContext, activityParty.PartyId);
                            Contact.Set(executionContext, new EntityReference("contact", Guid.NewGuid()));
                            Queue.Set(executionContext, new EntityReference("queue", Guid.NewGuid()));
                            User.Set(executionContext, new EntityReference("systemuser", Guid.NewGuid()));
                            Lead.Set(executionContext, new EntityReference("lead", Guid.NewGuid()));
                        }
                    }
                    else
                    {
                        trace.Trace("*****Contact assigned*****");
                        Contact.Set(executionContext, activityParty.PartyId);
                        Queue.Set(executionContext, new EntityReference("queue", Guid.NewGuid()));
                        User.Set(executionContext, new EntityReference("systemuser", Guid.NewGuid()));
                        Lead.Set(executionContext, new EntityReference("lead", Guid.NewGuid()));
                        Account.Set(executionContext, new EntityReference("account", Guid.NewGuid()));
                    }
                }
                break;
            }
        }
        else
        {
            trace.Trace("*****Email is null*****");
            Queue.Set(executionContext, new EntityReference("queue", Guid.NewGuid()));
            Contact.Set(executionContext, new EntityReference("contact", Guid.NewGuid()));
            User.Set(executionContext, new EntityReference("systemuser", Guid.NewGuid()));
            Lead.Set(executionContext, new EntityReference("lead", Guid.NewGuid()));
            Account.Set(executionContext, new EntityReference("account", Guid.NewGuid()));
        }
    }

    #region Properties
    [Input("E-mail")]
    [ReferenceTarget("email")]
    public InArgument<EntityReference> Email { get; set; }

    [Output("Account")]
    [ReferenceTarget("account")]
    public OutArgument<EntityReference> Account { get; set; }

    [Output("Contact")]
    [ReferenceTarget("contact")]
    public OutArgument<EntityReference> Contact { get; set; }

    [Output("Lead")]
    [ReferenceTarget("lead")]
    public OutArgument<EntityReference> Lead { get; set; }

    [Output("Queue")]
    [ReferenceTarget("queue")]
    public OutArgument<EntityReference> Queue { get; set; }

    [Output("User")]
    [ReferenceTarget("systemuser")]
    public OutArgument<EntityReference> User { get; set; }
    #endregion        
  }
}

So we are upgrading our internal CRM system from 4.0 to 2011, and this was a plugin that was on a workflow. 因此,我们将内部CRM系统从4.0升级到2011,这是工作流程中的一个插件。 I didn't have the original source code so I didn't really know what the code was doing. 我没有原始源代码,所以我真的不知道代码在做什么。 But I decompiled the original .dll file after I exported the solution. 但是在导出解决方案后,我反编译了原始的.dll文件。 I tried to rewrite the code for CRM 2011, and here is what I have. 我试图重写CRM 2011的代码,这就是我所拥有的。 After I tested the workflow, I get error saying: "Expected non-empty Guid." 在测试了工作流程之后,出现错误消息:“预期的非空Guid”。 The code goes to the very last line after the loop then gives me the error. 代码进入循环后的最后一行,然后给我错误。 Here is the trace: 这是跟踪:

Workflow paused due to error: Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Expected non-empty Guid.Detail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ErrorCode>-2147220989</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>Expected non-empty Guid.</Message>
  <Timestamp>2013-02-21T23:46:37.0376093Z</Timestamp>
  <InnerFault>
   <ErrorCode>-2147220970</ErrorCode>
    <ErrorDetails xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
    <Message>System.ArgumentException: Expected non-empty Guid.
Parameter name: id</Message>
    <Timestamp>2013-02-21T23:46:37.0376093Z</Timestamp>
    <InnerFault i:nil="true" />
    <TraceText i:nil="true" />
 </InnerFault>
 <TraceText>[Microsoft.Xrm.Sdk.Workflow: Microsoft.Xrm.Sdk.Workflow.Activities.RetrieveEntity]
[RetrieveEntity]
    *****Tracing Initiated*****
    *****IOrganizationService created*****
    *****Entity logical Name: email*****
    *****Entity ID: c49e4c7c-8724-de11-86ce-000c290f83d7*****
    *****Retrieve Request declared*****
    *****Retrieve Response executed*****
    *****businessEnitity retrieved*****
    *****Activity Party Name: contact*****
    *****Activity Party Id: 79ed3a33-8eb9-dc11-8edd-00c09f226ebb*****
    *****Activity Party not null*****
    *****Contact assigned*****
    *****foreach ended*****</TraceText>
</OrganizationServiceFault>
   at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.Retrieve(String entityName, Guid id, ColumnSet columnSet, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType)
   at Microsoft.Crm.Extensibility.InprocessServiceProxy.RetrieveCore(String entityName, Guid id, ColumnSet columnSet)
   at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.Retrieve(String entityName, Guid id, ColumnSet columnSet)
   at Microsoft.Crm.Workflow.Services.RetrieveActivityService.<>c__DisplayClass1.<RetrieveInternal>b__0(IOrganizationService sdkService)
   at Microsoft.Crm.Workflow.Services.ActivityServiceBase.ExecuteInTransactedContext(ActivityDelegate activityDelegate)
   at Microsoft.Crm.Workflow.Services.RetrieveActivityService.ExecuteInternal(ActivityContext executionContext, RetrieveEntity retrieveEntity)
   at Microsoft.Crm.Workflow.Services.RetrieveActivityService.Execute(ActivityContext executionContext, RetrieveEntity retrieveEntity)
   at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
   at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

I've received different errors or no errors, but I know its not working 我收到了其他错误或没有错误,但是我知道它不起作用

First, I suggest you to list errors in your question. 首先,我建议您列出问题中的错误。 It will be much easier to answer you and to avoid -1s. 回答您的问题和避免出现-1秒将更加容易。 :) Second, use tracing service in workflow. :)其次,在工作流中使用跟踪服务。

ITracingService tracingService = context.GetExtension<ITracingService>();
tracingService.Trace("I'm tracing something....");

What should happen if Contact with specified email is not found? 如果找不到与指定电子邮件的联系人 ,该怎么办? You have to handle this case. 您必须处理这种情况。 Probably it fails here. 可能在这里失败。 Post error log in question, to check this. 发布有问题的错误日志,以进行检查。

If I'm to give a shot-from-the-hip answer, I'd guess this is the problem is that you in some cases don't get a match and filter out everything. 如果我要给出一个发人深省的答案,我想这是问题所在,因为在某些情况下您没有比赛并过滤掉所有内容。 Then, you get null somewhere (or try to refer to an empty guid, or try to select an attribute that hasn't been entered so that, although it's defined, it's not served). 然后,您在某处得到null (或尝试引用一个空的 guid,或尝试选择一个尚未输入的属性,以便尽管已定义该属性,但仍未提供)。

What exact errors do you get? 您得到什么确切的错误? When do you get them and when don't you? 什么时候得到它们,什么时候不得到?

Also, some issues with the code that I've noticed (not the solution but still might be improved). 另外,我注意到的一些代码问题(不是解决方案,但仍可能会得到改善)。

Typo in the name. 错字的名字。 I think you wanted ContactReference . 我认为您想要ContactReference

[Output("output")]
[ReferenceTarget("contact")]
public OutArgument<EntityReference> ContactRefernce { get; set; }

I'd design the query in a bit different way. 我将以某种不同的方式设计查询。 Since you know what address you want to match, you might want to filter precisely that. 由于您知道要匹配的地址,因此您可能希望对其进行精确过滤。 Also, You seem only to be needing the guid for the match based on the email so you only need to fetch that. 另外,您似乎只需要基于电子邮件的比赛向导,因此您只需要提取该向导即可。

private Guid MatchSenderWithExistingContact(
  IOrganizationService service, String fromAddress)
{
  QueryExpression query = new QueryExpression
  {
    EntityName = "contact",
    ColumnSet = new ColumnSet("emailaddress1"),
    Criteria = new FilterExpression
    {
      Filters =
      {
        new FilterExpression
        {
          Conditions =
          {
            new ConditionExpression(
              "emailaddress1", ConditionOperator.Equal, fromAddress)
          }
        }
      }
    }
  };

  EntityCollection retrieveMultipleRequest = service.RetrieveMultiple(query);
  IEnumerable<Entity> entities = retrieveMultipleRequest.Entities;
  return entities.FirstOrDefault().Id;
}

You might want to put the declaration of the query on step-by-step syntax. 您可能希望将查询的声明放在逐步语法上。 I prefer it this way because it's more convenient when creating advanced queries. 我更喜欢这种方式,因为它在创建高级查询时更加方便。 However, the part when you iterated and used break is definitely better off as shown above. 但是,如上所示,当您迭代和使用中断时,该部分无疑会更好。

Happy coding! 编码愉快!

It might behoove you to use the tracing. 您可能应该使用该跟踪。 Usually, I declare the tracing object as a member variable in the plugin class and then write to it at every operation. 通常,我在插件类中将跟踪对象声明为成员变量,然后在每次操作时将其写入。 That way, at least I know where manure hits the AC and can log the value of the variables right before that. 这样,至少我知道肥料在哪里击中AC,并且可以在此之前记录变量的值。

private ITracingService trace;

public void Execute(IServiceProvider serviceProvider)
{
  trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
  _trace.Trace("Tracing successful!");
  throw new Exception("Intentional! Nice.");
}

Just keep it mind that the trace won't show unless an uncaught exception occurs. 请记住,除非发生未捕获的异常,否则不会显示跟踪。 In fact, I've intentionally crashed the execution on occasion just to see what's in the variables. 实际上,我偶尔会故意使执行崩溃,只是为了查看变量中的内容。 So remember that if you've got a global try-catch , you'll need to re-throw the exception manually. 因此请记住,如果您具有全局try-catch ,则需要手动重新引发异常。

Upside of this method is that you can tracing both on-premise and on-line. 这种方法的好处是您可以在内部和在线进行跟踪。 It works for all plugin registrations except the asynchronous. 它适用于除异步之外的所有插件注册。 There are work-arounds for that too but that wasn't the topic of your question and I've digressed enough already. 也有针对性的解决方法,但这不是您要讨论的话题,而且我已经讲够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM