I am experiencing an error in CRM workflows which run custom activities which reference common assembly from GAC, but different versions. The situation is as following:
Assembly A and assembly B (both custom activities) reference assembly C which contain a base class (inheriting from CodeActivity) for A and B as well as crmsvcutil generated class. Assembly C exists in GAC with multiple versions. Now, I created a new attribute in CRM, regenerated early types with crmsvcutil, updated the version of assembly C to 1.0.0.3 and put it into GAC, rebuilt assembly B (which uses the new attribute) and updated it using plugin registration tool.
The error shows up in workflows which reference both assembly A and B with an error message that "assembly.type" cannot be converted to "assembly.type". In base class (assembly C) we set an assembly property to be able to work with strong types:
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
var type = Type.GetType("Microsoft.Crm.Workflow.SynchronousRuntime.WorkflowContext, Microsoft.Crm.Workflow, Version=5.0.0.0");
type.GetProperty("ProxyTypesAssembly").SetValue(serviceFactory, typeof(XrmServiceContext).Assembly, null);
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
It seems to me that CRM caches the base class together with proxy types and tries to use it on assembly B, despite that it references new version of C. If I create a workflow with just activity from assembly B, it works fine, it is only if the assembly A is referenced in same WF and before B.
This is a problem now in production environment and I am trying to find a fix for it. I know I can update assembly A to use new version of C and I did it in test environment, but since there are a lot of more assemblies then two, many tests must be performed.
- Can I somehow point updated assembly B to an older version of C(and use indexer with attribute name for new attribute)? I tried reverting assembly version of C to 1.0.0.2, compiling again B, but then I get an error that assembly cannot be updated in plugin registration tool.
- Can someone explain how and where does an assembly keep version of a referenced assembly. How does this work in .NET in general?
The strangest thing is that I tried to copy the base class and early types class into the assembly B (in it's own namespace), completely remove the reference to assembly C, updated in plugin registry tool and I got exactly the same error, this time that "AssemblyC.type" cannot be converted to "AssemblyB.type". I don't understand how when I completely removed reference to assembly C.
Any suggestion is appreciated, thanks in advance.
EDIT: I have just found out that this relates only to dialogs. It works fine with workflows. Does that ring any bell?