Five ways to improve Quality and Productivity of Dynamics 365 development

a.k.a – Once I did a session twice

Just like last year in Lisbon, I did a developer focused session during eXtreme365 in Dubrovnik. Last year I had full focus on how to develop plugins for analysis, primarily using the Plug-in Trace Log in the code and how to best analyze the results of it.
This year I took a bit wider approach with an ambition to help developers become more productive and get higher quality of their code. In this article I will go through the five different areas I covered in the session.

The presentation can be viewed and downloaded from SlideShare on this link.

Five ways

There are of course many different approaches that can help your development and just as many opinions as there are developers, but I focused on the following five areas:

  1. image
    Visual Studio Extensions

    Customizing Visual Studio for Dynamics 365 development
  2. C# Extensions
    Get more functionality from standard SDK types
  3. Base Classes
    Generalize behavior and structure of plugin classes
  4. VSTS Build Extensions
    Automate CI / CD for the Dynamics 365 platform
  5. XrmToolBox helping out
    A few tools to take your development the last kilometer

1. Visual Studio Extensions

Bildresultat för visual studio

VS extensions can make your development environment a bit more “aware” of Dynamics 365 and the special characteristics of development for the platform.
There are a few of these out there, and as always you start with looking for something from the “source”, i.e. Microsoft. They do have the Microsoft Dynamics 365 Developer Toolkit which unfortunately still does not support VS2017. That currently is a deal breaker for many of us, but there is hope! Matt Barbour announced during eXtreme365 that they now have a team of a handful people devoted to developer tooling, so we are looking forward to some improvements!
Another option which looks really good is the XrmToolkit extension by Simpler Software. It contains most of the features you might need and as a well polished addition to the VS experience. The downside here is of course that this is not a community effort, they charge for each developer on your team.
A community based option is the D365 Developer Extensions by MVP Jason Lattimer. These extensions got a true revival when support for VS2017 was introduced, while the one from Microsoft still does not have that.
With these extensions you can easily speed up your development by using project templates and item/class templates. These will add NuGet references to the CRM SDK and provide base classes to facilitate plugin development and much more.

2. C# Extensions

Creating your own C# extensions to existing classes is a great way to make these classes behave just the way You want to.
A classic example is to add a GetParent and GetChildren extensions to the Entity class from the SDK. That makes it so much easier to traverse the information structure to get related information:

var account = contact.GetParent(service, "parentcustomerid", "name", "revenue");
var cases = account.GetChildren(service, "incident", "customerid", "ticketnumber", "subject");
Bildresultat för c#

The first line gets the account referenced in the Parent Customer attribute of a contact, and returns the account with attributes Name and Revenue.
The second line gets all cases where the account is referenced in the Customer attribute, and returns Ticket Number and Subject for the cases.
The syntax to create the extensions above would be:

public static Entity GetParent(this Entity entity, IOrganizationService svc, string lookupattribute, params string[] attributes)
public static IEnumerable<Entity> GetChildren(this Entity entity, IOrganizationService svc, string childtype, string lookupattribute, params string[] attributes)

Other useful extensions to the Entity class are GetAssociated, Associate, Disassociate, Clone, Merge and so on.
There are a few really nice C# extension packages published, where one example is MVP Daryl LaBar’s DLaB.Xrm package that among other things contains very useful extensions to make the creation of QueryExpression objects so much easier.

3. Base Classes

Where the C# extensions make existing classes perform more actions than they used to, the base classes are an extra layer of code, taking care of all the boring plumbing and generalizing the behavior that you without them would have to write again and again for each plugin or other code executing in similar context.
Base classes for plugins are available in most VS Extensions, and I think anyone who has developed more than three plugins is definitely using existing base classes or have created their own. We just don’t like to repeat code. Period.
When you are building your plugins using a base class, you don’t directly implement the IPlugin interface from the SDK. Instead you inherit a class that implements the interface. The base class usually initiates the OrganizationService, TracingService and extracts the PluginExecutionContext, to make these directly available to the plugin developer through a custom “context”.
It is also a great way to add your own metrics to your code, without having to add timing functionality in all custom code. You can add all CRUD methods available on the OrganizationService directly on the custom context, which can then automatically write the actions to the Plug-in Trace Log, adding timestamps and timers and even automatic indentation of trace lines etc, to make the log easier to digest for efficient analysis.

4. VSTS Build Extensions


Building and deploying artifacts for the Dynamics 365 platform is not easy only using out of the box tools. To make it bearable, there are a few extensions to Visual Studio Team Services.First, most popular, and most diverse is the xRM CI Framework by Wael Hamze. This toolkit contains a number of custom tasks for VSTS related to Dynamics 365, such as Update Assembly, Update WebResources, Set Solution Version, Export Solution, Unpack Solution, Backup Online Instance, and many more.The second one, released by me and probably still most used by us at Innofactor, is called DevOps for Microsoft Dynamics 365. This extension does not contain all the tasks that Wael produced, but has the advantage of fully supporting Shuffle based operations where you with very detailed granularity can specify which solutions and data to export, and how to import that to target environments. More information about the Shuffle and the VSTS extensions can be found here: Build and Deploy Microsoft Dynamics 365 projects using VSTS.

Another VSTS extension that we use, though not related to Build and Deploy, is NuGet Package Manager from Microsoft. We use this for internal distribution of the base classes and C# extensions we use throughout all of our development. This way, we get a controlled delivery process for the tools we use to build our solutions.

5. XrmToolBox helping out

As we all know by now:


…and there is no process that cannot be improved by utilizing the power of a few XrmToolBox tools.

  • So if you are working with early bound classes, you simply must use the Early Bound Generator by Daryl LaBar to create just the style of classes that you need for your project.
  • If you are instead going late bound, try my Latebound Constants Generator to create constant files and classes for the entities, attributes and optionsets in your project. No more typos, no more inconsistent constant structures.
  • When you just want to try out your code, or perhaps create a one-time gadget to fix broken data, investigate something, or just want to play around with the SDK, you really should try the Code Now tool by Alex Shlega. This tool offers you an OrganizationService, and you can go where you want from that. The code can be compiled and executed immediately, or compiled into an exe file that you can ship to be executed on-site.
  • For me, who rarely do things early bound, the Metadata Browser by Tanguy Touzard himself helps me out a lot. I don’t investigate the system in the CRM UI, it is just too slow and clicky for me. I use this excellent XrmToolBox tool when there is anything metadata related I need to know.
  • A super simple click saver is the Plugin Auto Updater by Alexey Shytikov. With this tool you just connect to CRM, select a dll file on your disk, and as soon as that dll is updated on disk it will find corresponding plugin registration and update it in CRM. So when you are developing you just edit your code, compile the file, and a second later you can try it out in CRM. With no clicks.
  • I use FetchXML Builder when I need help to compose a QueryExpression query, but want to build it and be able to test it along the way. Just compose the query, and see corresponding C# code develop along with it. One day, it will have the possibility to generate WebAPI queries too…
  • Finally, my plugin development would not be the same without my personal favorite; the Plugin Trace Viewer. Since I don’t debug plugins and automated tests never cover everything, I make sure I get verbose and readable logs written from my code and my frameworks. And I investigate using PTV, since the OOB UX absolutely s*cks.


There is a sample solution from my session that can be downloaded or forked from GitHub:

It contains two plugin classes, ContactPlugin1 and ContactPlugin2, that do the same thing. The first is based on the plugin base class from Jason Lattimer’s D365 Developer Extensions for Visual Studio. The second one is based on the JonasPluginBase class available in GitHub package Rappen.Xrm.JonasPluginBase. This example class has been described in my blog previously: I get by with a little help from my [base class].

Registering the assembly and adding a step for Update Contact Fax, and adding a post image with all attributes can give you this log in the Plugin Trace Log:

19:19:17.996	*** Enter
19:19:18.407	[JPB] Context details:
  Step:  Plugin.ContactPlugin2: Update of contact
  Msg:   Update
  Stage: 40
  Mode:  0
  Depth: 1
  Corr:  6148b9d3-2875-4bdc-8a51-66dfa1e9bf6e
  Type:  contact
  Id:    7b143128-8d27-e811-a951-000d3a276633
  User:  10da6cc3-8627-e811-a954-000d3a26abad
  IUser: 10da6cc3-8627-e811-a954-000d3a26abad

19:19:19.074	[JPB] Incoming contact
  contactid = 7b143128-8d27-e811-a951-000d3a276633 (Guid)
  fax       = 0101-121212 (String)

19:19:19.085	Hello world
19:19:19.085	BEGIN Checking images
19:19:19.085	  PreImage count: 0
19:19:19.095	  PostImage count: 1
19:19:19.095	END Checking images
19:19:19.106	BEGIN Doing the things
19:19:19.106	  Entity is contact 7b143128-8d27-e811-a951-000d3a276633
19:19:19.106	  [JPB] Retrieve(account, 0f143128-8d27-e811-a951-000d3a276633, 2)
19:19:20.179	  [JPB] Retrieved in: 1074 ms
19:19:20.179	  Parent is account Alpine Ski House (sample)
19:19:20.241	  [JPB] RetrieveMultiple(incident)
19:19:20.316	  [JPB] Retrieved 2 records in: 76 ms
19:19:20.326	  Found 2 cases: CAS-01002-N7R1J4, CAS-01006-C1F4Z4
19:19:20.326	  BEGIN Looping cases
19:19:20.326	    Updating entity
19:19:20.326	    [JPB] Update(incident) 29143128-8d27-e811-a951-000d3a276633 (5 attributes)
19:19:20.463	    [JPB] Updated in: 139 ms
19:19:20.463	    Updating entity
19:19:20.463	    [JPB] Update(incident) 31143128-8d27-e811-a951-000d3a276633 (5 attributes)
19:19:20.568	    [JPB] Updated in: 103 ms
19:19:20.568	  END Looping cases
19:19:20.568	END Doing the things
19:19:20.568	[JPB] Internal execution time: 1491 ms
19:19:20.568	*** Exit

Once I did a session twice

What’s up with the subtitle?
Well, we were all overwhelmed by the interest for my session. In a room with ~70 seats we crammed in well over 100 people, and the organizers had to turn down another 40 something at the door. So they squeezed in another spot for me and I did the same session the next day too!

The presentation from eXtreme365 can be viewed and downloaded from SlideShare on this link.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.