That’s quite a mouthful, spent at least 3 minutes just trying to figure out an appropriate title for this article. This article does not just relate to early bound assemblies but also any other assembly that is not part of the Microsoft core global assembly cache or the custom Plugin assembly itself.
Let’s say you have a plugin or a custom workflow activity that needs to some fancy stuff and you wish to leverage an existing dynamic link library (DLL) from a 3rd party. Well you are out of luck if you are using Microsoft Dynamics CRM online (well almost!), drum roll please……..
I’m not going into the pros and cons of late binding vs. early binding that perhaps is a subject for another article however know that Microsoft’s official standing on this is to use Early Bound whenever this is possible to do so: Microsoft Dynamics CRM Best Practices
For now I am going to assume you are like me a sensible soul who values things like improved code readability, portability, reducing the chances of errors and being able to access CRM types properties, methods, and events at Compile time. If that’s the case this article will be very useful to you.
Oh no not that error again! or perhaps you received something similar to the following error message:
“System.Runtime.Serialization.SerializationException: Microsoft Dynamics CRM has experienced an error. -2147220970 “
What is going on?
Plugins and custom activity workflows that execute within Microsoft Dynamics CRM online always run in Sandbox isolation mode. This is to limit potential security vulnerabilities and reduce the chances of code doing something it really should not be doing on a operating system level.
If using an On Premise version of Dynamics CRM you have two options when registering a plugins isolation mode namely “sandbox” and “none”. If the latter the plugin is able to access other assemblies, resources and code outside of the security context of the CRM application (IIS). In addition other things such as accessing files directly on the file system or perhaps reading and writing to the Windows Registry.
Imagine a scenario, where you want all of the relevant entities and custom entities you have created within a Dynamics CRM solution available to you from multiple project types within Visual Studio, it could be for example:
- Plugin Project
- Workflow Project
- Data Integration Project
- Early Bound Common Project
Wouldn’t it be nice to be able to easily access the latest, one common early bound library from all those projects? I think so. The problem is the isolation mode, when you register your plugin assembly it will not include the Early Bound DLL, neither will the Custom Workflow activity assembly which means when the CRM application tries to access the early bound types it isn’t going to have a clue about what those things are and where to find them.
Great, so what are our options?
Well there are several and this is something I ranted on about in the Dynamics Community website (Error in Sandbox Plugin). Fortunately, I was able to get support and insights from Scott Durrow (if you don’t know he is the person who developed the excellent Ribbon Workbench Tool) and is well known by Microsoft, IBM and the Dynamics Community.
The general accepted view is “to not generate a separate assembly” but instead link to the project from within Visual Studio this means that the code will be included within each assembly you generate. That sounds OK … but… what if I don’t have the code? what if I have a number of 3rd party libraries that I wish to use rather than re-inventing the wheel?
It doesn’t meet those scenarios and the truth is I am just way too stubborn to accept something which to me doesn’t instinctively feel right. I like the idea of having all the early bound stuff encapsulated within it’s own library that can be then referenced from any type of application.
Our Answer: ILMerge
It’s name is as Ugly as it is to get up and running in the first place! ILMerge is a utility developed by Microsoft Research that allows multiple DLLs to be merged together into a single DLL Library.
Before we get into this epic drama it is worth mentioning that Microsoft do not officially recommend this approach as it has been shown to sometimes cause issues with Plugin assemblies and types not casting as expected leading to serialisation and plugin execution exceptions at run-time. The general consensus from the community would seem to be:
For Online and this Scenario:
- Avoid ILMerge if possible and instead look for open source alternatives and include the code in your Plugin and Custom workflow activity projects
- Add the early bound code class files to each and every CRM project and Solution. To make this easier use Add-Link from within Visual Studio (you reference the external file via a Link)
Of course for On Premise you have more options and can reference other libraries so long as the plugin is set to execute in the “None” isolation mode:
- Register the assembly on disk with any referenced assemblies in the same directory.
- Register the referenced assembly in the Global Assembly Cache (GAC)
If you were not to use ILMerge, you can achieve something similar to referencing a DLL (meaning you still have one master common library) doing it via a link instead. Linked project items in Solution Explorer, can be identified by the link indicator in its icon (a small arrow in the lower left corner).
By linking to a file, you can capture ongoing changes to a source file without having to manually update a copy whenever changes are made. However, if the underlying file is deleted, the link will be broken.
- In Solution Explorer, select the target plugin/workflow project
- On the Project menu, select Add Existing Item
- In the Add Existing Item dialog box, locate and select your Common Project early bound class items item you want to link
- From the Open button drop-down list, select Add As Link
Should I even bother to use ILMerge?
For simplistic plugins that are just referencing an early bound library and not lots of other third party DLL’s it is unlikely you will have issues with ILMerge. Even so the problem still exists of what to do when using Microsoft Dynamics CRM Online where your plugins/workflows need to leverage third party libraries and the Isolation mode is Sandbox as opposed to None. In that scenario this is not possible unless you Merge the assemblies and to see how to set that up I welcome you to read Part 2
All under under Creative Commons License