Answered by:
CRM 2011 custom workflow activity with early bound classes InvalidCastException

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
-
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
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, JohannesThursday, 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 missingI 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, JohannesThursday, 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