‘An unexpected error occurred’ and using early-binding in CRM plugins

Our plugin was throwing the error below when creating a new task record:

‘An unexpected error occurred.’

at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.Create(Entity entity, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, Boolean checkAdminMode, Dictionary`2 optionalParameters)
at Microsoft.Crm.Extensibility.InprocessServiceProxy.CreateCore(Entity entity)

We were not doing anything fancy that led to this error – except we used early-binding classes:

var task = new Task
{
	Subject = "New task",
	Description = "Some description..."
};

task.Id = _organisationService.Create(task);

Our plugin was deployed to the database, and we used ILMerge to package everything into a single DLL as required by CRM under this deployment type. This was not the cause of our problem.

The strange thing is the plugin only error when running asynchronously. Changing the plugin step to be synchronous and everything works fine.

It turns out that this is because there are different behaviours between the CRM execution context for synchronous versus that for asynchronous.

Let’s take a step back in order to fully understand this. The IOrganizationService instance has a non-public property _proxyTypesAssembly that points to the assembly where the early-binding classes are defined. This must be set for the service instance to be able to work with early-binding classes properly. When things are good, this is what it looks like when you debug:

The error occurs when this property is null.

So how does this property get set? In plugins we typically use an instance of IOrganizationServiceFactory to get access to an instance of IOrganisationService:

serviceFactory = (IOrganizationServiceFactory) serviceProvider.GetService(typeof (IOrganizationServiceFactory));
service = serviceFactory.CreateOrganizationService(userId);

It is at this point that the _proxyTypesAssembly property is set for the IOrganizationService instance by the IOrganizationServiceFactory.

Below is a screenshot of inspecting the IOrganizationServiceFactory when the plugin in running synchronously. Note that the public ProxyTypesAssembly property is automatically set.

Also note that the type of the IOrganizationServiceFactory instance (serviceFactory) is Microsoft.Crm.Extensibility.PipelineExecutionContext.

Below is a screenshot of the same plugin running asynchronously. Note that the public ProxyTypesAssembly property is null, and the type of the IOrganizationServiceFactory is different compare to when running synchronously.

This is why by default plugins that use early-binding work fine in synchronous mode, but fail when running asynchronously.

To fix this issue we need to set the ProxyTypesAssembly property of the IOrganizationServiceFactory instance. While this property is not exposed on this interface, Darko Micic has found that the IOrganizationServiceFactory interface can be casted to IProxyTypesAssemblyProvider, which allows us to set this property.

The code to retrieve an instance of IOrganizationService therefore becomes:

var serviceFactory = (IOrganizationServiceFactory) serviceProvider.GetService(typeof (IOrganizationServiceFactory));
var proxyTypesAssemblyProvider = serviceFactory as IProxyTypesAssemblyProvider;

if (proxyTypesAssemblyProvider != null)
{
	proxyTypesAssemblyProvider.ProxyTypesAssembly = Assembly.GetExecutingAssembly();
}

service = serviceFactory.CreateOrganizationService(userId);

Note that in Darko’s post he mentioned casting the execution context to IProxyTypesAssemblyProvider. In my debugging I have found that IOrganizationServiceFactory and IPluginExecutionContext actually points to the same instance when retrieved from the service provider. I therefore have chosen to cast the IOrganizationServiceFactory instance instead.

Advertisements

About Bernado

Based in Australia, I am a freelance SharePoint and Dynamics CRM developer. I love developing innovative solutions that address business and everyday problems. Feel free to contact me if you think I can help you with your SharePoint or CRM implementation.
This entry was posted in CRM. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s