locked
Upgrading custom workflow code for CRM 2011 RRS feed

  • Question

  • I am trying to upgrade C# code for a custom workflow activity from CRM 4 to CRM 2011.

    The following line is causing me some trouble, as I don't know how to upgrade it properly.

    Original code is:

          public Lookup accountId
            {
                get
                {
                    return (Lookup)base.GetValue(accountIdProperty);
                }
                set
                {
                    base.SetValue(accountIdProperty, value);
                }
            }

    The lookup was originally accessed as follows:

          Guid accountId = MatchSenderWithExistingAccount(crmService, this.sender);
                
                this.accountId = new Lookup("contact", accountId);

    So I've updated the lookup part to this:

     [Output("AccountId")]
            [ReferenceTarget("contact ")]
            [Default("00000000-0000-0000-0000-000000000000")]
            public OutArgument<EntityReference> AccountId { get; set; }

    And am trying to update the second line like this:

      Guid accountId = MatchSenderWithExistingAccount(service, SenderId.ToString());                 
                     
                      this.AccountId.Set(executionContext, new EntityReference("contact", accountId));

    But this isn't working. It builds, but when I try to register the dll I get the following error:

    Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Invalid default value: There is no entity name specified with property: AccountId of type EntityReference
    Detail: <OrganizationServiceFault xmlns="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <ErrorCode>-2147200995</ErrorCode>
      <ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
      <Message>Invalid default value: There is no entity name specified with property: AccountId of type EntityReference</Message>
      <Timestamp>2014-03-03T13:35:50.9340181Z</Timestamp>
      <InnerFault>
        <ErrorCode>-2147200995</ErrorCode>
        <ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
        <Message>Invalid default value: There is no entity name specified with property: AccountId of type EntityReference</Message>
        <Timestamp>2014-03-03T13:35:50.9340181Z</Timestamp>
        <InnerFault i:nil="true" />
        <TraceText i:nil="true" />
      </InnerFault>
      <TraceText i:nil="true" />
    </OrganizationServiceFault>
    
    Server stack trace: 
       at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    
    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at Microsoft.Xrm.Sdk.IOrganizationService.Create(Entity entity)
       at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.CreateCore(Entity entity)
       at Microsoft.Crm.Tools.PluginRegistration.RegistrationHelper.RegisterPlugin(CrmOrganization org, CrmPlugin plugin)
       at Microsoft.Crm.Tools.PluginRegistration.PluginRegistrationForm.btnRegister_Click(Object sender, EventArgs e)

    So I know that the upgraded version of the property is written wrongly as it says in the error message that there is no entity with that value. But I don't know how else to upgrade that specific piece of code. The way I've done it, I just found online - it's completely new to me, so I have no idea myself!

    Thanks.


    Monday, March 3, 2014 1:37 PM

All replies

  • The code looks ok, can you just check a small thing? in this line:

    [ReferenceTarget("contact ")]

    there is a space after contact, if it also inside your code remove it.
    Another thing, the value inside Guid accountId must be a Guid from a contact record (maybe it's better to rename the property to make it more clear)


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Monday, March 3, 2014 2:54 PM
  • Thanks for your reply. I removed the space, and the accountID is definitely a Guid from a contact record. Here's the code for the method that's called in the code above:

           private Guid MatchSenderWithExistingAccount(IOrganizationService crmService, string fromAddress)
            {           
                QueryByAttribute query = new QueryByAttribute("contact");
                query.Attributes.Add("emailaddress1");
                query.Values.Add(fromAddress);
                RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest();
                retrieveMultipleRequest.Query = query;
                RetrieveMultipleResponse retrieveMultipleResponse = (RetrieveMultipleResponse)crmService.Execute(retrieveMultipleRequest);
                Guid contactId = Guid.Empty;
                foreach (Entity busEntity in retrieveMultipleResponse.EntityCollection.Entities)
                {
                    contactId = (Guid)busEntity["contactid"];   
                    break;
                }
                  
                return contactId;
            }

    Monday, March 3, 2014 5:26 PM
  • looks like your Lookup typed property is accountId with a small a, and your attribute has AccountId with a capital A,  and that you are using this.AccountId...  is there another AccountId property somewhere.

    I see a lot of inconsistency when it comes to case.

    Monday, March 3, 2014 5:31 PM
  • That lookup code is part of the original, non-upgraded code, and is no longer used. It has been replaced by the following:

    [Output("AccountId")]
            [ReferenceTarget("contact ")]
            [Default("00000000-0000-0000-0000-000000000000")]
            public OutArgument<EntityReference> AccountId { get; set; }

    The Guid account Id is set to the value that's in the Output parameter called AccountId. I was just following the existing naming conventions when upgrading the code.

    Here is the complete code for my custom workflow activity:

    using System;
    using System.ServiceModel;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Collections;
    using System.Drawing;
    using System.Workflow.ComponentModel.Serialization;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.Runtime;
    using System.Activities;
    using Microsoft.Crm.Sdk.Messages;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Workflow;
    using Microsoft.Xrm.Sdk.Query;
    using Microsoft.Xrm.Sdk.Messages;
    using Microsoft.Xrm.Sdk.Client;
    
    namespace GetReceipientEmail
    {
        public class MatchSenderWithExistingCustomerActivity : CodeActivity
        {
            protected override void Execute(CodeActivityContext executionContext)
                {
                      IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();    
                      IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();                  
                      IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
                       
                      Guid accountId = MatchSenderWithExistingAccount(service, SenderId.ToString());                 
                     
                      this.AccountId.Set(executionContext, new EntityReference("contact", accountId));
    
                }
    
            private Guid MatchSenderWithExistingAccount(IOrganizationService crmService, string fromAddress)
            {           
                QueryByAttribute query = new QueryByAttribute("contact");
                query.Attributes.Add("emailaddress1");
                query.Values.Add(fromAddress);
                RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest();
                retrieveMultipleRequest.Query = query;
                RetrieveMultipleResponse retrieveMultipleResponse = (RetrieveMultipleResponse)crmService.Execute(retrieveMultipleRequest);
                Guid contactId = Guid.Empty;
                foreach (Entity busEntity in retrieveMultipleResponse.EntityCollection.Entities)
                {
                    contactId = (Guid)busEntity["contactid"];   
                    break;
                }
                  
                return contactId;
            }
                  
            
    
            [Input("Enter Sender ")]        
            [Default("")]
            public InArgument<String> SenderId { get; set; }
    
            [Output("AccountId")]
            [ReferenceTarget("contact")]
            [Default("00000000-0000-0000-0000-000000000000")]
            public OutArgument<EntityReference> AccountId { get; set; }
                
        }
    	
    }

    Tuesday, March 4, 2014 12:30 PM
  • Does anyone have any more ideas on this? I'd say I've written the upgraded version of AccountID wrongly, but I don't know what's wrong with it. I literally have no clue.

    Here's all the original code:

    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Collections;
    using System.Drawing;
    using System.Workflow.ComponentModel.Compiler;
    using System.Workflow.ComponentModel.Serialization;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.Runtime;
    using System.Workflow.Activities;
    using System.Workflow.Activities.Rules;
    using Microsoft.Crm.Sdk;
    using Microsoft.Crm.SdkTypeProxy;
    using Microsoft.Crm.Workflow;
    using Microsoft.Crm.Sdk.Query; 
    
    namespace GetReceipientEmail
    {
        [CrmWorkflowActivity("Find Customer with specified email address")]
    
        public class MatchSenderWithExistingCustomerActivity : System.Workflow.Activities.SequenceActivity
        {
            protected override System.Workflow.ComponentModel.ActivityExecutionStatus Execute(System.Workflow.ComponentModel.ActivityExecutionContext executionContext)
                {
                      IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
                      IWorkflowContext context = contextService.Context;
                      ICrmService crmService = context.CreateCrmService(); 
                      Guid accountId = MatchSenderWithExistingAccount(crmService, this.sender);
                      this.accountId = new Lookup("contact", accountId);
                      return ActivityExecutionStatus.Closed;
                }
             private Guid MatchSenderWithExistingAccount(ICrmService crmService, string fromAddress)
            {
                QueryByAttribute query = new QueryByAttribute();
                query.EntityName = EntityName.contact.ToString();
                query.Attributes = new string[] { "emailaddress1" };
                query.Values = new string[] { fromAddress };
                RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest();
                retrieveMultipleRequest.Query = query;
                retrieveMultipleRequest.ReturnDynamicEntities = true;
                RetrieveMultipleResponse retrieveMultipleResponse = (RetrieveMultipleResponse)crmService.Execute(retrieveMultipleRequest);
                Guid contactId = Guid.Empty;
                foreach (BusinessEntity busEntity in retrieveMultipleResponse.BusinessEntityCollection.BusinessEntities)
                {
                    contactId = ((Key)(((DynamicEntity)busEntity)["contactid"])).Value;
                    break;
                }
                  
                return contactId;
            }
    
            public static DependencyProperty senderProperty = DependencyProperty.Register("sender", typeof(string), typeof(MatchSenderWithExistingCustomerActivity));
            [CrmInput("Sender")]
            public string sender
            {
                get
                {
                    return (string)base.GetValue(senderProperty);
                }
    
                set
                {
                    base.SetValue(senderProperty, value);
                }
            }
            public static DependencyProperty accountIdProperty = DependencyProperty.Register("accountId", typeof(Lookup), typeof(MatchSenderWithExistingCustomerActivity));
            [CrmOutput("AccountId")]
            [CrmReferenceTarget("contact")]
    
            public Lookup accountId
            {
                get
                {
                    return (Lookup)base.GetValue(accountIdProperty);
                }
                set
                {
                    base.SetValue(accountIdProperty, value);
                }
            }

    The upgraded version is in the post above this.

    Thanks.

    Tuesday, March 4, 2014 4:23 PM