问题
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. 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. 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. 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. I tried to rewrite the code for CRM 2011, and here is what I have. After I tested the workflow, I get error saying: "Expected non-empty 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)
回答1:
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. :) 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.
回答2:
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).
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.
[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.
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.
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.
来源:https://stackoverflow.com/questions/14970636/crm-2011-custom-workflow