July 21, 2015

Visual Studio 2015 Shared Projects and CRM Plugins Development

Visual Studio 2015 is now available and inside the new features and improvements there is one that I like very much: Shared Projects. A Shared Project is intended to share easily the code between different platforms.
For C# projects this was already possible using (portable) class libraries and adding the assembly to the main project references.

Which is the big advantage of Shared Projects for a Dynamics CRM developer?
With Shared Projects the code is NOT compiled to a separate assembly but directly inside the main assembly of your project.

This is can be very useful for Plugin and Custom Workflow Activity development, because now we can create a common library with CRM methods to be used inside our plugins WITHOUT the need to use ILMerge for creating a single assembly in order to be registered inside Dynamics CRM.

As example I created a small shared project containing a simple method to check the current CRM Version:
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
namespace CRM.Common
{
    public static class Utils
    {
        public enum CRMVersion
        {
            Unknown = 0, CRM2011 = 2011, CRM2013 = 2013, CRM2015 = 2015
        }

        public static CRMVersion GetCRMVersion(IOrganizationService service)
        {
            RetrieveVersionRequest versionRequest = new RetrieveVersionRequest();
            RetrieveVersionResponse versionResponse = (RetrieveVersionResponse)service.Execute(versionRequest);
            string version = versionResponse.Version;
            if (version.StartsWith("5")) { return CRMVersion.CRM2011; }
            if (version.StartsWith("6")) { return CRMVersion.CRM2013; }
            if (version.StartsWith("7")) { return CRMVersion.CRM2015; }
            return CRMVersion.Unknown;
        }
    }
}
After I created a normal Class Library project for my plugin and I added the Shared Project to the solution and a reference inside the Class Library:

The plugin code is very simple, it throws an exception indicating the CRM version:
using Microsoft.Xrm.Sdk;
using System;
using static CRM.Common.Utils;

namespace CRM.MyPlugin
{
    public class MyPlugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            CRMVersion version = GetCRMVersion(service);
            throw new InvalidPluginExecutionException(version.ToString());
        }
    }
}
If we compile the solution only a single assembly is generated and if we analyze it using ILSpy we can confirm that the Shared Project is compiled inside the main assembly:

And the plugin works without issues:


Shared Projects can be very useful for Dynamics CRM development because will definitely improve the quality and the reuse of the code.

Shared Projects are also available for Visual Studio 2013 as separate addon, you can download from here: Shared Project Reference Manager

July 14, 2015

New Dynamics CRM for phones iOS App and getFormFactor method

Yesterday Microsoft released the new iOS App for Dynamics CRM (iTunes link). The app only works with CRM versions 7.1 and higher, this means currently can be used only with CRM Online instances that received the Update 1.

The new App supports JavaScript so I wanted to test a little script with the method getFormFactor.

getFormFactor (MSDN link) is a new method introduced with CRM Online 2015 Update 1 returning a numeric value based on the current device. The possible values are:

ValueForm Factor
0Unknown
1Desktop
2Tablet
3Phone

The script I wrote is:
function accountOnLoad() {
    var factor = Xrm.Page.context.client.getFormFactor();
    var message = "The Form Factor is: " + factor;
    Xrm.Utility.alertDialog(message);
}
And the result is:

Note: the script is not called when a new record is created.