locked
CRM 2011 custom workflow activity with early bound classes InvalidCastException RRS feed

  • Question

  • Hi,

    I'm developing a custom workflow activity that calls a method that references early bound classes.

    I'm getting the following error when running the workflow:

     

    Workflow paused due to error: Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'Microsoft.Xrm.Sdk.Entity' to type 'Myspace.Xrm.Base.my_defect'.
       at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
       at Microsoft.Xrm.Sdk.Linq.PagedItemCollection`1.MoveNext()
       at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
       at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
       ...
      at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
       at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

     

    Here's my code snippet:

    protected override void Execute(CodeActivityContext executionContext)
            {
                Context = executionContext.GetExtension<IWorkflowContext>();

                //I have to do the following setting in my plugins to get them to work with early bound classes. However, in workflow it throws cast exception.
                //((Microsoft.Crm.Extensibility.PipelineExecutionContext)Context).ProxyTypesAssembly = typeof(MyServiceContext).Assembly;

                //Create an Organization Service
                ServiceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
               
                // Create service with context of current user
                Service = ServiceFactory.CreateOrganizationService(Context.InitiatingUserId);
               
                // Create service with context of admin
                ServiceAsAdmin = ServiceFactory.CreateOrganizationService(null);

                ...

                var defect = (from e in Context.CreateQuery<my_defect>()
                              where e.Id == id
                              select e).FirstOrDefault();
            }

    Does anyone know what I'm missing?

    Thank you.


    • Edited by Stephanus N Thursday, October 20, 2011 10:18 AM
    Thursday, October 20, 2011 10:13 AM

Answers

All replies

  • I think your problem must be coming in where you are using the 'defect' var.  That is where it will attempt to cast the item.  Try:

    IEnumerable<my_defect> defects = from e in Context.CreateQuery<my_defect>()
    where e.Id == id
    select e;
    if (defects.Count() > 0)
    {
    my_defect defect = defects[0];
    ...
    }

     

    Tuesday, October 25, 2011 1:36 PM
  • Is there even a CreateQuery method in IWorkflowContext? I too wonder if it is possible to use early bound classes with custom workflow activities...
    BR, Johannes
    Thursday, November 3, 2011 11:13 AM
  • In a custom workflow in 2011 you will use a CodeActivityContext as passed in to the Execute method of your custom workflow.  This can be used to generate a CrmServiceContext thusly:

    protected override void Execute(CodeActivityContext executionContext)           
     IWorkflowContext _context = executionContext.GetExtension<IWorkflowContext>();
                InitiatingUserId = _context.InitiatingUserId;
                _tracingService = context.GetExtension<ITracingService>();
                IOrganizationServiceFactory serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
                _service = serviceFactory.CreateOrganizationService(_context.UserId);
    }
    
    


    The _service created of course supports .CreateQuery() as well as proxy types generated through the CrmSvcUtil.exe.

    Thursday, November 3, 2011 12:40 PM
  • Ah ok JBlaeske, I tried to work with the IWorkflowContext like posted above, wondering why there is no CreateQuery method - because that method spawns from the xrm.sdk.client namespace. To instantiate the context class one must pass the constructor something that works with the IOrganizationServer interface.

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

                //Create the context
                IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
                IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
                OrganizationServiceContext myservicecontext = new OrganizationServiceContext(service); //was missing

     

    I tried it i.e. with one of of my custom workflow activities:

                var integrationrecord = (from c in myservicecontext.CreateQuery<s3_integrationstarter>()
                                         where c.s3_starter.Contains("blabla")
                                         select c).FirstOrDefault();

                tracingService.Trace(integrationrecord.s3_starter);

     


    BR, Johannes
    Thursday, November 3, 2011 4:18 PM
  • You mention the generic context.  You can also create a type-safe context with the classes generated from the CrmSvcUtil.exe.  The code there will depend on your namespace used for your proxy classes.  Therefore I didn't add it.  Sorry.

    Thursday, November 3, 2011 4:32 PM
  • Hi,

    Please have a look at my blog post which describes how to set the ProxyTypesAssembly property for the WorkflowContext.

    http://blog.orangegecko.com.au/2011/12/05/custom-workflow-activities-and-early-bound-entity-classes/

    Hope that helps!

     

    • Proposed as answer by Orange Gecko Saturday, December 10, 2011 1:10 AM
    • Marked as answer by Stephanus N Monday, December 12, 2011 4:08 AM
    Saturday, December 10, 2011 1:10 AM
  • Hi

    There are more than only one context classes. You should use this solution here:

    http://blog.micic.ch/net/crm-2011-plugin-and-early-bound-entities

    This will work for every context.

    • Proposed as answer by Darko Micic Friday, March 16, 2012 7:28 PM
    Friday, March 16, 2012 6:22 PM