Monday, March 26, 2018

Updated CRM Workflow Utilities

I’ve just made a round up updates to my workflow utilities. I’ve added new functionality to most of them and did some refactoring on the backend. I’m also dropping support for the 2011/2013 version of the solutions I’d been keeping up mostly because they weren’t being downloaded very much and it frees up time for other endeavors. The current solution will work for anything 2015 and later (v7.0+).
If you’ve got suggestions for new functionality, make them on the corresponding GitHub issues page.

CRM Email Workflow Utilities

GitHub    Latest Release
  • Email Business Unit
  • CC Business Unit
  • Email Security Role
  • CC Security Role
  • Email Team
  • CC Team
  • Email Queue Members
  • CC Queue Members
  • Email Connection - NEW
  • CC Connection - NEW
  • Delete Email Attachments
  • Delete Email Attachments By Name
  • Send Draft Email
  • Check Email Attachments Present & Count
  • Create Template – NEW

CRM DateTime Workflow Utilities

GitHub    Latest Release
  • Add Business Days
  • Add Days
  • Add Hours
  • Add Minutes
  • Add Months
  • Add Years
  • DateDiff - NEW
  • Date Difference Seconds - NEW
  • Date Difference Hours
  • Date Difference Minutes
  • Date Difference Days
  • Date Difference Months
  • Date Difference Years
  • Get Second Number - NEW
  • Get Minute Number - NEW
  • Get Hour Number - NEW
  • Get Day Number
  • Get Month Number
  • Get Year Number
  • Get Month Name
  • Get Day Number Of Week
  • Get Day Number Of Year
  • Get Day Of Week
  • Get Quarter Number Of Year
  • Get Week Number Of Year
  • Get Month Start/End Dates
  • Get Quarter Start/End Dates
  • Get Week Start/End Dates
  • Get Year Start/End Dates
  • Is Between
  • Is Business Day
  • Is Same Day
  • Relative Time String
  • ToDateTime
  • To UTC String
  • Set Time - NEW
  • Get Formatted Date String - NEW
  • Set DatePart – NEW

CRM String Workflow Utilities

GitHub    Latest Release
  • B64 Decode - NEW
  • B64 Encode - NEW
  • Contains
  • Create Empty Spaces
  • Decode Html - NEW
  • Encode Html - NEW
  • EndsWith
  • Join
  • Length
  • PadLeft
  • PadLeft Dynamic
  • PadRight
  • PadRight Dynamic
  • Random String - NEW
  • Regex Extract
  • Regex Match
  • Regex Replace
  • Regex Replace With Space
  • Replace
  • Replace With Space
  • Reverse
  • StartsWith
  • Substring
  • ToLower
  • ToTitleCase
  • ToUpper
  • Trim
  • Word Count
  • Remove HTML - NEW
  • Url Encode - NEW
  • Url Decode- NEW

CRM Numeric Workflow Utilities

GitHub    Latest Release
  • Add
  • Average
  • Divide
  • Max
  • Min
  • Multiply
  • Random Number
  • Random Number Between
  • Round
  • Subtract
  • ToDecimal
  • ToInteger
  • Truncate
  • Absolute Value - NEW
  • IsStringNumeric – NEW

CRM Note Workflow Utilities

GitHub    Latest Release
  • Check Attachment
  • Copy Note
  • Move Note
  • Delete Attachment
  • Delete Attachment By Name
  • Delete Note
  • Update Note Text
  • Update Note Title

Monday, March 12, 2018

Log to Application Insights from Microsoft Flow or Logic Apps

If you haven’t checked out Azure Application Insights yet you might want to give it a look. It’s got a lot to offer in terms of  logging, monitoring, alerting, multi-colored charts and graphs, etc. Microsoft provides libraries for several languages to make logging things easier but ultimately you’re just making HTTP requests to a public endpoint.

There isn't a connector which lets you write to Application Insights but logging can be done fairly easily with a HTTP Action. I’d suggest referencing the telemetry API to figure out what options are available and how data needs to be structured as my examples won’t contain everything available.


All the requests will be:

Method: POST

In each request body:
  • Replace “time” with the Flow utcNow() function
  • Replace "00000000-0000-0000-0000-000000000000" with your Application Insights key
  • Replace “properties” with any custom key/value pairs you wish to track


Diagnostic log messages

  • Replace “message” with whatever you want to trace


User actions and other events

  • Replace “name” with the name of the event
  • Replace inside “measurements” with a measurement name (string) and value (numeric) or set to null if not using


Performance measurements such as queue lengths not related to specific events

  • Replace inside “metrics” with a metric name (string), kind (integer), value (double) – see API for additional details


Logging the duration and frequency of calls to external components that your app depends on


Recommended replacements, doesn’t need to follow this format exactly
  • Replace “id” with an id of some sort - Application Insights libraries have a way of generating an id if you care to track it down
  • Replace “name” with the HTTP verb and Url Absolute Path
  • Replace “resultCode” with the HTTP Status Code
  • Replace “duration” with the elapsed time
  • Replace “success” with true/false
  • Replace “data” with the HTTP verb and Url
  • Replace “target” with Url Host
  • Replace “type” with something describing the type of request
Tracking the time it took to execute a different HTTP request within a Flow was a little difficult. Catching the request Start and End times was fairly easy but I couldn’t seem to find a way to easily calculate the duration. I cheated a little and created an Azure Function to do it for me – not exactly ideal but whatever. Once I had that I could plug the “Calculate Duration” HTTP Action Body into the “duration”. The “resultCode” and be pulled directly from the HTTP Action. To populate “success” I used a simple formula which looked at the Status Code and set accordingly.

if(equals(outputs('Test_HTTP')['statusCode'], 200),true, false)


The Azure Function to calculate duration looks like this:

And that’s about it, you should start seeing results in your Application Insights instance.

Thursday, March 1, 2018

D365 Developer Extensions – Out of Beta

Install from Visual Studio under Extensions & Updates.

This is the new version of CRM Developer Extensions.

Wondering what changed? Check out the Change Log.

I recommend that if using with VS 2015, uninstall the older release of CRM Developer Extensions just in case. 

What's it's got currently

Numerous project & item templates
  • Plug-ins
  • Custom workflows
  • Web resources
  • TypeScript
  • Testing
  • Build your own
Web resource deployer
  • Manage mappings between D365 organizations and Visual Studio project files
  • Publish single items or multiple items simultaneously
  • Filter by solution, web resource type & managed/unmanaged
  • Download web resources from D365 to your project
  • Open D365 to view web resources
  • Compare local version of mapped files with the D365 copy
  • Add new web resources from a project file
  • TypeScript friendly
  • Compatible with Scott Durrow's Spkl deployment framework
Plug-in deployer & registration
  • 1 click deploy plug-ins & custom workflows from Visual Studio without the SDK plug-in registration tool
  • Integrated ILMerge
  • Compatible with Scott Durrow's Spkl deployment framework which allows defining registration details in code
Solution packager UI
  • 1 click download and extraction of solution to a Visual Studio project
  • Re-package solution files from a project and import to D365
Plug-in trace log viewer
  • Easily view and search the Plug-in Trace Log
  • Ability to delete logs
Custom intellisense
  • Custom autocomplete for entity and attribute names from your organization

For additional details, see the Wiki.

Post any bugs, ideas, or thoughts in the Issues area.

Monday, February 5, 2018

D365 Developer Extensions - Beta

It’s long overdue but the next iteration of my Visual Studio extension CRM Developer Extensions (now called D365 Developer Extensions) is ready for some testers. It was nearly a ground up rebuild to hopefully make it a bit easier to maintain and have people contribute to.

What's it's got currently:
  • Web resource deployer*
  • Plug-in deployer & registration*
    * Compatible with Scott Durrow's Spkl deployment framework
  • Solution packager UI
  • Plug-in trace log viewer
  • Numerous project & item templates
  • Intellisense for organization entity & attribute names
For Visual Studio 2015 & 2017

You can check out the documentation here to get an overview of the functionality.

I’m hoping that most of the kinks are worked out but there are bound to be some yet – thus the Beta release.

Grab the latest release here and manually install. Once a few people have kicked the tires I’ll get it up on the Visual Studio Marketplace.

Post any bugs, ideas, or thoughts in the Issues area of GitHub.

Monday, December 18, 2017

Creating a Custom Virtual Entity Data Provider

One of the cool new features of Dynamics 365 Customer Engagement (or whatever we’re calling it now) v9.0 is Virtual Entities. A quick overview is you weren’t aware, Virtual Entities let you surface external data into the system as if it were actually present in the organization database (naturally with some caveats). This means it could be in forms, views, reports, available from an API, etc. Read-only at the moment, with the promise of create, update, and delete sometime in the future. With that said, this is the foundation for what is to come.

If you aren’t looking to code anything and happen to have some data exposed via an OData v4 endpoint, has a Guid for a primary key, and is not secured or only secured by a static token that can be included in the query string, then you are in good shape. You might actually be able to configure via the Virtual Entity Data Sources UI under Administration.

Of course the problem is that if you do happen to already have a web service for your data, it probably doesn’t meet all those criteria. Enter the Custom Virtual Entity Data Provider. At the time of writing, the first thing you see the linked page is a message saying that it would be better to re-build your existing data provider than to take this approach. Sounds encouraging :) Lets move on.

Again, at the time of writing the documentation: Sample: Generic virtual entity data provider plug-in is in fact incomplete. Mainly it’s missing some key steps in the set up and the information on debugging is TBD. But if you do look at the code, it might seem a little familiar. In the example we’re writing a plug-in for the RetrieveMultiple message and putting our own content in the Output “BusinessEntityCollection”. It doesn’t show Retrieve but again all the really happens is you put your own data in the Output “BusinessEntity”. Nothing we couldn’t do in CRM 2011 but remember this is the foundation of things to come.

The other item to note on the sample is the use of a QueryExpressionVisitor. Stop and think for a moment, if people are going to use Advanced Find to look for your external data, how does the system translate that into something your data source can use? Well it doesn’t, you need to handle that yourself. Microsoft has given us the Microsoft.Sdk.Data namespace to assist with converting a QueryExpression into some other format. Considering how many operators Advanced Find has between all the different data types, it seems like monumental task to try and support everything. So later when we’re defining the attributes for our external data, don’t forget you can mark them as unsearchable so they can’t be used in Advanced Find.

The code for this is located in GitHub so your can take a look at it. I’m not going to spend too much time on that because the real value comes from walking through the setup I think. Also note in my example, the web service I hooked up to didn’t provide Guids for identifiers but instead had some random characters. Since there was only about 9.7k records for the purposes of making this example work with something I found a bit funny, I created some Guids and joined them up with the provided random character ids and stored them in the plug-in. Obviously, the Guid is important of course so when you try and open a record from a view, the system needs to know which record to retrieve.

Chuck Norris jokes

So I chose to bring Chuck Norris jokes in as external data. As it turns out there is an existing web service for that: I’ll just explain how the code is working and if you want to grab it later and look, feel free. FYI – there might not be the most “politically" correct” content on this site so be warned.

RetrieveMultiple plug-in

The API lets you search on a keyword. To keep my example minimal I extracted the first value from the first condition in the QueryExpression. Once I had that I made a search request to the API with that key word and got some results back. From there I parsed that data and created new Entity records for each result matching the schema I defined. I used a predefined list to match the API id to a Guid – naturally you’d use the Guid returned from your API. Once I had the Entities in an EntityCollection I put them in the Output “BusinessEntityCollection” and that was it. In case someone didn’t enter any search conditions, instead of returning everything I opted to use the API’s “random” feature and just returned a single result.

Retrieve plug-in

The plug-in Target Id will be the Guid you set in RetrieveMultiple. So here I grab that and use it to look up a specific joke’s random character id. As it turns out there was not a service method to retrieve a single record, it expects you’re just going to build a url and open it in the browser I guess. With that being the case I grabbed the HTML content and parsed out the values I needed for my Entity. Once I had that I put it into the Output “BusinessEntity and was done.

Lots of pictures

Here’s the walkthrough on the setup. I’m using v9.0.0.7 of the Plug-in Registration Tool for this which you can get from NuGet.

First off, register your assembly – don’t worry about adding any steps


Choose the new Register New Data Provider option


We’re creating a new solution here so add the details


Data Source Entity “Create New Data Source”


Choose your plug-in assembly & set Retrieve/RetrieveMultiple handlers you’ve created



I had a few issues with crashes so watch out.

In D365

Under Administration –> Virtual Entity Data Sources – New

Choose the data provider you created


Now you should have a new Virtual Entity in your solution


Add the new Data Source and assembly to your solution (optional)

At this point you’ll already see a Virtual Entity for the Data Source

Create a new Virtual Entity – this is the one for the actual data

Set the Data Source to the one you just created



Create any other data fields, views, etc. – the external names aren’t that important I don’t think since the plug-in is doing the mapping from the real source


Publish All Customizations

And that’s it

Advanced Find or View

Get random joke – no search criteria
Get a joke containing the search word – this is all the plug-in handles in conjunction with the Chuck Norris joke web service

Final thoughts

Obviously the data is only going to be returned as fast as the web service can provide it If it’s slow, user experience is going to suffer. Getting your provider in Azure would probably be helpful.
I didn’t look at how paging might work, but that’s something that will need to be figured out at some point.

You also noticed that we didn’t explicitly register any steps on our plug-ins since the setup did that for us. I’m still wondering how you’d go about debugging with the Profiler with no steps (remember the TBD earlier?).

Get the code on GitHub: