Saturday, February 12, 2011

CRM 2011 plug-in tips and tricks (part 1) - Develop and Debug in Sandbox Isolation Mode

There are a lot of examples of writing CRM 2011 plug-ins in the SDK, but none of them really describe the process of testing, troubleshooting, and properly debugging you're plug-in code.  As a result I see a lot of developers wasting time and making guesses at the reasons for their plug-in errors. So in the following posts I will outline some of the gotchas and tricks I've learned so far while developing plug-ins for CRM 2011.

#1.  Develop and Debug in Sandbox Isolation Mode (its faster)

If you ever want your plug-ins to work on CRM Online then you need to make sure you're plug-ins work in sandbox isolation mode.  And you will be surprised to learn what works and doesnt work when in sandbox mode.  These are just a few of the things I've run into that don't work in sandboxed plug-ins
The best way to avoid being surprised by any of these issues is to make sure you do all development in testing in Sandbox mode.  You don't want to be surprised when you deploy your plug-in to CRM Online and find out you're using some .NET function that isn't supported.

Also, it is now actually easier to debug plug-ins when they are sand-boxed. When registering a plug-in, you have three options of where the plug-in can be stored.
  1. On Disk - The plug-in assembly is stored on the CRM server file system (in the Server\Bin\Assembly folder). 
  2. Database - The plug-in assembly is actually uploaded to the CRM server and stored in the CRM database.
  3. GAC - The plug-in is stored in the global assembly cache on the CRM server.

In previous versions of CRM if you wanted to debug a plug-in your only option was to register the plug-in on DISK.  This meant that everytime you made a change to your plug-in code you had to re-copy the file to the assembly folder  (which also meant you had to restart IIS and the CRM Asynchronous service).

Now you can debug the plug-in even if it's stored in the database and in sandbox mode, and it's actually a much faster development cycle because you can avoid restarting IIS and the Asyc service.  

Debugging a plug-in is simple, just follow the instructions in the SDK found here.  Essentially, there are three differences from debuggin an on-disk plug-in
  1. Add the SandboxDebugPlugins key to the registery (see the instructions in the SDK).
  2. Copy the PDB file for your plug-in assembly to the server\bin\assembly folder.
  3. In Visual Studio, attach the debugger to all of the "Microsoft.Crm.Sandbox.WorkerProcess.exe" processes.
It is actually un-necessary to reset IIS or the sandbox processes when making changes to your plug-in, all you need to do is copy the new PDB to assembly folder and re-upload the new plug-in DLL to the server.

In fact, you can make the process of re-uploading the plug-in DLL to CRM very fast with a simple console application. All the console app needs to do is connect to the CRM server, and update the "Content" attribute of the PluginAssembly record for your plug-in. The following code should do the trick:

QueryExpression query = new QueryExpression(PluginAssembly.EntityLogicalName);
query.ColumnSet = new ColumnSet("name");
query.Criteria.Conditions.Add(new ConditionExpression("name", ConditionOperator.Equal, myAssemblyName));
EntityCollection retrievedAssemblies = _serviceProxy.RetrieveMultiple(query);
if (retrievedAssemblies.Entities.Count > 0)
{
     PluginAssembly myAssembly = (PluginAssembly)retrievedAssemblies.Entities[0];

     byte[] bytes = File.ReadAllBytes(myAssemblyPath);
     myAssembly.Content = Convert.ToBase64String(bytes);

     _serviceProxy.Update(myAssembly);
}

If you also automate the copying of the PDB file into the server\bin\assembly folder then you can actually get at pretty quick debugging cycle going.