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 we 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:image

  1. 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

VS extensions can make your development environment a bit more “aware” of Dynamics 365 and the special characteristics of development for the platform.

Bildresultat för visual studioThere 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 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 Classesimage

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

imageBuilding 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.


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 ~50 seats we crammed in ~70 people, and the organizers had to turn down another 40 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.

Labels: , , , ,