locked
Advanced Workflow Error : "An unexpected error occurred." RRS feed

  • Question

  • Hi All,

    I have created Advance workflow which creates Invoice from contract. ( we have this requirement where we want to create invoice from contract every year).


    I am trying to create this in visual studio and register this workflow assembly using Plug in registration tool. while registering this plugin it gives following error

    Unhandled Exception: System.Web.Services.Protocols.SoapException: Server was unable to process request.
    Detail: <detail><error>
      <code>0x80040216</code>
      <description>An unexpected error occurred.</description>
      <type>Platform</type>
    </error></detail>
       at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
       at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
       at PluginRegistrationTool.CrmSdk.CrmService.Create(BusinessEntity entity) in C:\Microsoft CRM 4.0 SDK\tools\pluginregistration\Web References\CrmSdk\Reference.cs:line 212
       at PluginRegistrationTool.RegistrationHelper.RegisterPluginType(CrmOrganization org, CrmPlugin plugin) in C:\Microsoft CRM 4.0 SDK\tools\pluginregistration\RegistrationHelper.cs:line 313
       at PluginRegistrationTool.PluginRegistrationForm.btnRegister_Click(Object sender, EventArgs e) in C:\Microsoft CRM 4.0 SDK\tools\pluginregistration\PluginRegistrationForm.cs:line 488


    Following is Code that I am putting in my CreateInvoice class. Is there any problem with the coding this workflow? can i satisfy this requirement (creating invoice from contract) by any other better way?


    using System;
    using System.Workflow.Activities;
    using System.Workflow.ComponentModel;
    using Microsoft.Crm.Sdk;
    using Microsoft.Crm.SdkTypeProxy;
    using Microsoft.Crm.Workflow;
    using Microsoft.Crm.Sdk.Query;
    
    
    namespace CreateInvoiceWorkFlow
    {
    	[CrmWorkflowActivity("Create Invoice from Contract")]
    	public class CreateInvoice : System.Workflow.Activities.SequenceActivity 
    	{
    		//input property
    		public static DependencyProperty ContractIdProperty = DependencyProperty.Register("ContractId", typeof(Lookup), typeof(CreateInvoice));
    		[CrmInput("ContractId")]
    		[CrmReferenceTarget("contract")]
    		public Lookup ContractId
    		{
    			get { return (Lookup)base.GetValue(ContractIdProperty); }
    			set { base.SetValue(ContractIdProperty, value); }
    		}
    
    		// Output property  
    		public static DependencyProperty invoiceIdProperty = DependencyProperty.Register("InvoiceId", typeof(Lookup), typeof(CreateInvoice));
    		[CrmOutput("InvoiceId")]
    		[CrmReferenceTarget("invoice")]
    		public Lookup InvoiceId
    		{
    			get { return (Lookup)base.GetValue(invoiceIdProperty); }
    			set { base.SetValue(invoiceIdProperty, value); }
    		}
    
    		
    		protected override System.Workflow.ComponentModel.ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
    		{
    
    			IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
    			IWorkflowContext context = contextService.Context;
    			// Obtain IcrmService so we can call into CRM SDK to retrieve 
    			// accounts                
    			ICrmService crmService = context.CreateCrmService();
    
    			
    			// this.sender property will have the email address that needs to be matched.
    			Guid invoiceId = CreateInvoiceBasedOnContract(crmService, this.ContractId.Value.ToString());
    			
    
    			// Set the accountId output property to return this data
    			// back to the calling workflow
    			this.InvoiceId = new Lookup("invoice", invoiceId);
    
    			//this.contactId = new Lookup("contact",contactId);
    
    			return ActivityExecutionStatus.Closed;
    
    
    		}
    
    		/// <summary>
    		/// Retrieves the contract objects
    		/// </summary>
    		/// <param name="myService">The CRM Service</param>
    		/// <param name="searchId">The Search Id String</param>
    		/// <returns>Account Object</returns>
    		public contract RetrieveContract(ICrmService myService, string searchId)
    		{
    
    			Guid Id;
    
    			Id = new Guid(searchId);
    
    			// Create the column set object that indicates the fields to be retrieved.
    			AllColumns cols = new AllColumns();
    
    			// Retrieve the contact.
    			// The EntityName indicates the EntityType of the object being retrieved.
    			contract myContract = (contract)myService.Retrieve(EntityName.contract.ToString(), Id, cols);
    
    			return myContract;
    
    		}
    		
    		private System.Guid CreateInvoiceBasedOnContract(ICrmService crmService, string contractId)
    		{
    			contract baseContract = RetrieveContract(crmService, contractId);  
    			
    		  invoice myInvoice = new invoice();
    		  
    		  myInvoice.name = "Test Invoice create";
    
    		  myInvoice.ispricelocked = CrmTypes.CreateCrmBoolean(false);
    
    		  myInvoice.customerid = CrmTypes.CreateCustomer(EntityName.account.ToString(), baseContract.customerid.Value);
    
    		  myInvoice.transactioncurrencyid = CrmTypes.CreateLookup(EntityName.transactioncurrency.ToString(), baseContract.transactioncurrencyid.Value);
    
    		  myInvoice.ownerid = CrmTypes.CreateOwner(EntityName.systemuser.ToString(), baseContract.ownerid.Value);
    
    		  Guid Id;// = new Guid("d0690029-572e-de11-ba46-00237d9e0372"); ;
    		  Id = crmService.Create(myInvoice);
    		  
    		  
    		  return Id;
    		  
    		}
    
    
    	}
    
    
    }
    Wednesday, April 22, 2009 10:39 AM
    Answerer

Answers

  • Hi
        Change 'invoiceIdProperty' to 'InvoiceIdProperty' (capital letter) and it schould be ok.
    everything is a matter of probability...
    Wednesday, April 22, 2009 12:25 PM
  • it depends on your public property name...see my public propery is InvoiceId


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



    so DependencyProperty  should be <<Public propertyname>> + "Property"  so it have to be InvoiceIdProperty..

    Tuesday, December 22, 2009 3:06 PM
    Answerer

All replies

  • Hi
        Change 'invoiceIdProperty' to 'InvoiceIdProperty' (capital letter) and it schould be ok.
    everything is a matter of probability...
    Wednesday, April 22, 2009 12:25 PM
  • Thanks!!

    it's working now...
    Wednesday, April 22, 2009 1:43 PM
    Answerer
  • Wait. Why did that work? Is it just that return properties have to be capitalized, or does it have to exactly match a property name from somewhere else? If so, how do I find the correct capitalization for the different ids? Do you know of a list I could refer to?

    In my case I am trying to return a system user. Would SystemuserIdProperty be correct?
    Tuesday, December 22, 2009 2:53 PM
  • it depends on your public property name...see my public propery is InvoiceId


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



    so DependencyProperty  should be <<Public propertyname>> + "Property"  so it have to be InvoiceIdProperty..

    Tuesday, December 22, 2009 3:06 PM
    Answerer
  • That was a helpful explanation, thank you.

    However, I am still getting an identical error to the one you had. Here is my code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Workflow.Activities;
    using System.Workflow.ComponentModel;
    using Microsoft.Crm.Workflow;
    using AddressMatchUser.CrmSdk;
    
    namespace CrmCustomWFActivity
    {
        [CrmWorkflowActivity("Find user that should own postal code of specified address")]
        public class MatchUserByPostalCode : System.Workflow.Activities.SequenceActivity
        {
    
            public CrmService Service;
            public CrmAuthenticationToken token;
        // Activity code goes here.
    
        // Input property
            public static DependencyProperty senderProperty = DependencyProperty.Register("Postal Code", typeof(string), typeof(MatchUserByPostalCode));
    
            [CrmInput("Postal Code")]
            public string sender
            {
                get
                {
                    return (string)base.GetValue(senderProperty);
                }
                set
                {
                    base.SetValue(senderProperty, value);
                }
            }
            // Output property
            public static DependencyProperty SystemUserIdProperty = DependencyProperty.Register("SystemUserId", typeof(Lookup), typeof(MatchUserByPostalCode));
            [CrmOutput("SystemUserId")]
            [CrmReferenceTarget("systemuser")]
            public Lookup SystemUserId
            {
                get
                {
                    return (Lookup)base.GetValue(SystemUserIdProperty);
                }
                set
                {
                    base.SetValue(SystemUserIdProperty, value);
                }
            }
    
            private Guid MatchUserPostalCode(CrmService Service, string fromPostalCode)
            {
                string queryCode;
                if (fromPostalCode.Length != 5)
                    return (Guid.Empty);
                if (fromPostalCode.Substring(0, 1) == "0")
                    queryCode = fromPostalCode.Substring(1,2);
                else
                    queryCode = fromPostalCode.Substring(0,3);
    
                ColumnSet cols = new ColumnSet();
                cols.Attributes = new string[] { "new_pastorid" };
    
                ConditionExpression condition = new ConditionExpression();
                condition.AttributeName = "new_name";
                condition.Operator = ConditionOperator.Equal;
                condition.Values = new string[] {queryCode};
    
                FilterExpression filter = new FilterExpression();
                filter.FilterOperator = LogicalOperator.And;
                filter.Conditions = new ConditionExpression[] { condition };
    
                QueryExpression query = new QueryExpression();
                query.EntityName = EntityName.new_postalcode.ToString();
                query.ColumnSet = cols;
                query.Criteria = filter;
    
                Guid systemuserId = Guid.Empty;
    
                BusinessEntityCollection Pastors = Service.RetrieveMultiple(query);
                foreach (systemuser Pastor in Pastors.BusinessEntities)
                {
                    // Pick the first systemuserid.
                    systemuserId = Pastor.SystemUserId.Value;
                    break;
                }
                return systemuserId;
            }
    
            protected override System.Workflow.ComponentModel.ActivityExecutionStatus Execute(System.Workflow.ComponentModel.ActivityExecutionContext executionContext)
            {
                IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
                IWorkflowContext context = contextService.Context;
               
                // Obtain IcrmService so we can call into CRM SDK to retrieve accounts
    
                token = new CrmAuthenticationToken();
                token.AuthenticationType = 0;
                token.OrganizationName = "rcgcrm";
    
                Service = new CrmService();
                Service.CrmAuthenticationTokenValue = token;
                Service.Credentials = System.Net.CredentialCache.DefaultCredentials;
    
                // this.sender property will have the postal code that needs to be matched.
                Guid systemuserId = MatchUserPostalCode(Service, this.sender);
                // Set the systemuserId output property to return this data back to the calling workflow
                this.SystemUserId = new AddressMatchUser.CrmSdk.Lookup();
                this.SystemUserId.Value = systemuserId;
                return ActivityExecutionStatus.Closed;
            }
    
        }
    }

    Any ideas?

    Thank you.
    Tuesday, December 22, 2009 3:53 PM
  • Ok. This works now. There had to be a match between the Registered property and the name of the dependencyproperty. Sorry I did not understand the explanation completely the first time.

    In my case
            public
     static
     DependencyProperty senderProperty = DependencyProperty.Register("Postal Code"
    , typeof
    (string
    ), typeof
    (MatchUserByPostalCode));
    Had to be

            public
     static
     DependencyProperty senderProperty = DependencyProperty.Register("sender"
    , typeof
    (string
    ), typeof
    (MatchUserByPostalCode));
    I would like to have changed the name of senderProperty instead, but since I already tried to register it would give me errors about not being able to find "senderProperty" when I would try to register it again.

    Anyway, it's not the end of the world to have to use the name "sender." Thanks for the help.
    Tuesday, December 22, 2009 5:04 PM