Simple, No fuss, Dynamics 365 Deployment Task Runner

Why? I've used the Dynamics Developer Toolkit since it was first released by MCS for CRM4! I love the functionality it brings however the latest version is still in beta, it isn't supported on VS2017 and there isn't a date when it's likely to be either (yes, you can hack it to make it work but that's not the point J). Rather than using an add-in Visual Studio project type, I've been attracted by the VS Code style simple project approach and so I decided to create a 'no-frills' alternative that uses a simple json config file (and that can be used in VS2017). What?

Deploy Plugins & Workflow Activities - Uses reflection to read plugin registration information directly from the assembly. This has the advantage that the plugin configuration is in the same file as the code. You can use the 'instrument' task to pull down the plugin configuration from Dynamics and add the metadata to your classes if you already have an existing project. Deploy Web Resources – deploy webresources from file locations defined in the spkl.json configuration. You can use the 'get-webresources' task to create the spkl.json if you already have webresources deployed. Generate Early Bound Types – Uses the spkl.json to define the entities to generate each time the task is run to make the process repeatable. Profile management – An optional profile can be supplied to select a different set of configuration from spkl.json. E.g. debug and release build profiles.

How? Let's assume you have a project in the following structure: Solution |-Webresources | |-html | | |-HtmlPage.htm | |-js | | |-Somefile.js |-Plugins | |-MyPlugin.cs |-Workflows | |-MyWorkflowActivity.cs

On both the Plugin and Workflows project, Run the following from the Nuget Console: Import-Package spkl This will add the spkl to the packages folder and the metadata CrmPluginConfigurationAttribute.cs that is used to mark up your classes so that spkl can deploy them. Some simple batch files are also included that you can use to get started. If you already have plugins deployed, you can run the following command line in the context of the Plugins folder: spkl instrument This will prompt you for a Dynamics Connection, and then search for any deployed plugins and their matching .cs file. If the MyPlugin.cs plugin is already deployed it might end up with the following Attribute metadata: [CrmPluginRegistration("Create","account", StageEnum.PreValidation,ExecutionModeEnum.Synchronous, "name,address1_line1", "Create Step",1,IsolationModeEnum.Sandbox, Description ="Description", UnSecureConfiguration = "Some config")] A spkl.json file will be created in the project directly similar to: { "plugins": [ { "solution": "Test", "assemblypath": "bin\Debug" } ] }

If you now build your plugins, you can then run the following to deploy spkl plugins You can run instrument for the workflow project using the same technique which will result in code similar to the following being added to your workflow activity classes: [CrmPluginRegistration( "WorkflowActivity", "FriendlyName","Description", "Group Name",IsolationModeEnum.Sandbox)]

…and then run the following to deploy: spkl workflow
To get any currently deployed webresources matched to your project files you can run the following from the Webresource project folder: spkl get-webresources /s:new
    Where new is the solution prefix you've used This will create a spkl.json similar to the following: { "webresources": [ { "root": "", "files": [ { "uniquename": "new/js/somefile.js", "file": "js\somefile.js", "description": "" }, { "uniquename": "new/html/HtmlPage.htm", "file": "html\HtmlPage.htm", "description": "" } ] } ] }

You can then deploy using: spkl webresources Profiles For Debug/Release builds you can define multiple profiles that can be triggered using the /p:<profilename> parameter. { "plugins": [ { "profile": "default,debug", "assemblypath": "bin\Debug" }, { "profile": "release", "solution": "Test", "assemblypath": " bin\Release" } ]


The default profile will be used if no /p: parameter is supplied. You can specify a profile using: spkl plugins /p:release
Referencing a specific assembly rather than searching the folder If you have multiple plugins in a single deployment folder and you just want to deploy one, you can explicitly provide the path rather than using the folder search. E.g. { "plugins": [ { "assemblypath": "bin\Debug\MyPlugin.dll"

Adding to a solution If you'd like to automatically add the items deployed to a solution after deployment you can use: { "webresources": [ { "root": "", "solution": "Test", Combining spkl.json Perhaps you want to have a single spkl.json rather than multiple ones per project. You can simply add them all together: { "webresources": […], "plugins": […] }

Multiple project deployments Since the spkl.json configuration files are searched from the current folder, you can deploy multiple plugins/webresources using a single spkl call from a root folder. I'll be updating the github documentation page as things move forwards.

How to get assistance without the Relationship Assistant!

Dynamics 365 has brought with it a new and amazing feature called the 'Relationship Assistant'. It is part of a preview feature (unsupported and US only) called 'Relationship Insights' which promises to bring some amazing productivity tools to the Dynamics 365 platform. Relationship Assistant shows actionable cards in both the web client and mobile client using a mix of both plain old filter conditions and machine learning.

Read about Relationship Assistant Read about Relationship Insights

Machine Learning Cards One of the most exciting part of the Relationship Assistant is the use of machine learning to examine the contents of your emails and predict what you need to do next: Customer Question Card

Issue Detected Card

'Plain old query' Cards Whilst the machine learning aspects may be out of our reach to us mere mortals at this time, the cards that are based on simpler filter conditions such as 'Due Today' and 'Meeting Today' are items that can be easily shown in a dashboard without this preview feature. Here are some examples of information that can be gained from simple date queries: Due Today Card

Meeting Today Card

Missed Close Date Card

(Images taken from the Relationship Assistant Card reference - Create your own 'Relationship Assistant' Dashboard The main challenge with producing information shown above is the date aspect to the query. We can easily show a single set of records that use the 'Next X days' type of operator, but you could not easily use 'todays' date in a dashboard chart – at least not until CRM2015 introduced calculated fields. Now it is rather easy to produce a dashboard similar to the following:

The key feature of dashboards is that they are can be tailored to show your own data which can be drilled into to show the underlying records. This is comparable to the 'actionable' aspect of the relationship assistant where you could drill into the tasks due to 'today' and open them to work upon. Notice the field 'Due' that can have the value 'Completed', 'Due Next 7 Days', 'Due Today', 'Overdue', or 'Scheduled'. This field isn't stored as a persistent field in the database, but instead it is a calculated field so there are no nightly jobs or workflows required to update a field based on the current date. Adding a 'Due Status' field to an Activity Entity

Create a solution with the Activity Entity that you want to add the 'Due Status' field to Create a new field called 'Due Diff' – this will give us a field that shows the number of days before/after the activity due date.

Click 'Edit' and type the expression DiffInDays(scheduledstart, Now()) Note: This assumes that this is an Appointment and you want to use the scheduledstart date to control the due date. Add a new global Option Set that holds the possible values for the Due status Create a new Calculated Option Set field called 'Due' on the Activity record. Use the Existing Option Set created above.

Click 'Edit' on the Calculated Field type and add the following logic: Create a chart something like: Publish and add the charts to a dashboard!

Of course other more complex options exist but with all the excitement and awesomeness of Machine Learning it is important to remember that we can achieve great things with just the right kind of queries, charts and dashboards!

Hope this helps!

SharePoint Integration Reloaded – Part 5 (belated)

In previous articles in this series we've talked about the differences between Server Side Sync and the old List Component. Since I published the first articles, a new MSDN article on the topic has been posted which I thought would be good to signpost folks to => Important considerations for server-based SharePoint integration. One of the topics that has come up recently for people using Server Side Sync to SharePoint is the 5000 item limit of Document Libraries which has led to a bit of panic amongst some so I thought I'd dispel the rumours!     Here are the facts about the Throttling Limitation 1) You can see how many items you have in a Document Library by opening the site in SharePoint and selecting 'Site Content' from the left hand navigation menu. The number of items will show below the Document Library name – this includes documents and folders. 2) If you have more than 5000 items you can still use Server Side Integration with SharePoint provided that you only use the default sort order of the document view in CRM.The default sort is by Location Ascending. You can change this to sort Descending but if you change the sort to any other column you will receive the error "Throttling limit is exceeded by the operation" 3) If you have a record with only 2 documents in the associated document locations folder you will still not be able to sort by any other column other than Location if the root Document Library has more than 5000 items overall. 3) If the user clicks on 'Open SharePoint' then they will be able to do all the sorting they need since the limitation is not experienced by the native SharePoint interface – only the CRM document lists. I find that this sort limitation is not an issue because I encourage users to use SharePoint freely due to its rich interface. Don't try and hide SharePoint from them because it's important to understand the way in which documents are stored and the additional features that SharePoint has to offer. The documents view in CRM is simply to be used as a quick reference for documents associated with the CRM Record. Hope this helps!

New version of Network Visualisations for Dynamics CRM

Many of you will have seen (and possibly used) my previous version of NetworkView. Thank you for all the feedback you've given. The top 5 points of feedback were:

Can I show connections on the graph? Can I show custom entities on the graph? I have very large graphs which makes it hard to understand what is going on. I have records owned by Teams but I cannot see that on my graph. How do I know which node is the one that I've opened the graph from?

With version 1.6 I've addressed these points as follows: Showing Connections You can now show connections between entities! The connection roles that are discovered (e.g. Partner, Influencer etc.) are listed so that you can then highlight all the connections of a particular role on the graph by selecting the role. Loading connections may be turned on or off on a per-entity basis in the configuration.

Activity Overflow Since most of the time folks are only interested in the links between records via activities rather than the actual activities themselves, the graph now loads the first 10 records and then shows an overflow node that you can double click to load the next 5 activities. Under the covers, all that activities that match the FetchXml filter are loaded and the links worked out but the links are shown to and from the 'overflow' node rather than the individual activities until you expand the node.

Iteration Limit Network graphs can often grow to a large size if you have many connections, the graph will now pause loading after a set number of iterations and ask if you want to load more. The most frequent cause of graph growth is where there are connections that are also users – for this reason, the graph will supress connections that have the same email domain as any of your users.

Team Ownership In addition to showing users who own records and participate on activities the graph now shows Teams in same list and allows highlighting records that are associated with that team.

Root Node identification You can now see which record you started the graph from highlighted in green. Cycle Mode When you first load the Network view, the users and connection are cycled through so that the various cohorts on your graph are highlighted for your viewing pleasure! This can be turned off by clicking the cycle button and the configuration controls if it is on by default. Configurable The graph is now configured using a customisable web-resource named: dev1/js/NetworkViewConfig1033.js To add your custom configuration you simply need to edit this web resource and publish the changes. You can use the following options:


The number of iterations of the load mechanism before prompting the 'Load More' option. Default:10


Output trace to F12 console whilst loading. This is good for working out why your graph looks the way it does Default: false


Turn on the demo cycle when the graph first loads. Default: false


The query to fetch connections. The placeholder {0} must be inserted where the ID filter should be added.


The query to fetch activities. The placeholder {0} must be inserted where the ID filter should be added.


Array of Entities to load (including custom entities)

Each Entity configuration has the following fields:


The name of the entity used in messages.


The logical name of the entity to load


The logical name of the attribute that holds the display name of the record.


The logical name of the attribute that holds the unique ID of the record


The logical name of the parent Record ID when hierarchical loading is enabled.


True when the graph should show activities for this entity


True when the graph should show connections for this entity (connections must be supported by this entity)


True when the parent/child relationships should be traversed using the hierarchical operators.


The query to get the records. The placeholder {0} must be inserted where the filter conditions should be added.


Holds an array of joins to other entities.

  Installation To install or upgrade from the previous version :

Install SparkleXRM v7.2.8 or later Install the NetworkView managed solution

The usual disclaimer & license applies. Special thanks goes to @dynamiccrmcat for help with testing this version. @ScottDurow

Refreshed Connections UI Solution

Following on from my recent video series called 'Building a Refreshed Connections UI using SpakleXRM' this post shows you how to use the final solution to add a bit of sparkle to the otherwise slightly neglected connections feature in Dynamics CRM. Connections first saw an appearance in CRM2011 replacing the customer relationships entity. The big deal about connections was that they could connect any entity to any other entity using the same lookup field and could be viewed from either side of the relationship. This made them very powerful for creating complex relationships between contacts, contacts, cases and opportunities such that the relationships would be equally discoverable from both sides.

Two sided - If you add a link between John Smith and Contoso you can see that connection on the Contoso record as well as the John Smith record. Behind the scenes this is achieved by two connections being created with the duplicate having the Connect To and Connect From lookups reversed. The connection that you created is marked as the 'Master' and when opening the non-master connection you are actually shown the Master record. Ubiquitous – A common ask from users is to see all relationships in one place. Since connections support multiple types of records you can have a single list that shows connections between many types of record. The Connection Role is used to determine the type of relationship and the Connection Role Category can be used to group the types of roles together (e.g. Business, Sales Team, Stakeholders etc.) Customisable Intersect Entity – There are existing attributes such as Effective Start and Effective End that are useful when modelling relationships that change over time but you can also add you own fields. The downside of this of course is that those fields will be visible for all connections irrespective of the entities types that are being connected unless you do some hiding/showing dynamically.

I've always loved the connection entity but it hasn't received the 'Refreshed UI' treatment in recent releases which is why I created the Refreshed Connection UI Solution. Current Experience (CRM2015) This is what the current experience is on the Opportunity Form:

So, far so good, but if you add a custom connections sub grid you get the following. Perhaps the biggest drawback is that the Add New (+) button cannot be used on the form connections sub-grid.

If you then use the associated sub grid you get the following. Adding connections uses the old style Ribbon Form.

New Experience Using the new SparkleXRM Refreshed Connections UI this is the experience you'll get:

Installing: The code is all in github if you want to take look - otherwise you can install the managed solution. 

You will need to install version 7.2.7 of SparkleXRM (or later) Install SparkleXRM Metadata Server (if you want multi language support) Install the Refreshed Connections UI Managed Solution 


You can add the component to any form that supports connections by using 'Add Web Resource'

Select the Web Resource named con_/html/Connections.htm Within the Web Resources properties dialog on the Formatting tab set the height in Rows and un-check 'Display Boarder' and change the Scrolling to 'Never'

Again, within the Web Resource properties dialog on the General tab you can pass the following properties:

entities – (Optional) A Comma separated list of entity logical names that you want to support in the lookup. By default the entities will be account,contact,opportunity,systemuser pageSize – (Optional) The number of rows to display per page. By default a size of 10 will be used. view – (Optional) The name of the view to use (e.g. All Stakeholders). By default the Associated view will be used

The usual disclaimer & license applies.

Turbo Forms: Get your JavaScript ready for CRM2015 Update 1

With the introduction of 'Turbo Forms' in CRM2015 Update 1 I thought I'd give you a heads up on what you'll need to address in your JavaScript to support this new form rendering engine. The Dynamics CRM Team Blog has a very good article on the changes but there have been some misunderstandings of the statement 'we have parallelized as many operations as possible'. In actual fact the script loading of custom web resource scripts has not really changed since CRM2013 - It remains the same as I describe in my CRM2013 Script Loading Deep Dive. The operations that are parallelized with turbo form rendering are the internal form load operations rather than custom ones. Custom JavaScript loading has always been parallelized since CRM2013. Turbo Form Page Differences Before Turbo Forms both global scripts and your custom web resources would have been loaded into a content IFRAME within the main window each time you navigate between records.

The biggest change with Turbo Forms is that the content IFRAME is kept in memory and re-used for performance reasons. This parent content IFRAME is even kept in memory between navigation between different entity types. Any custom JavaScript is then loaded into a child IFRAME (via the ClientApiWrapper.aspx page) so that when you navigate between records they are re-loaded.

SparkleXRM solutions already have a load order mechanism that ensure that your custom scripts are loaded in order that they are needed. Impact on unsupported code If your JavaScript is using only supported SDK calls then there will be no impact from this new loading mechanism. Sometimes it is necessary to use unsupported functions or referencing parameters of the Content IFRAME (such as the query string). Since your custom JavaScript is now running in the context of the ClientApiWrapper (rather than the content IFRAME) any reference to window methods such as window.openStdWin or window.location.href will fail. In order to access these objects you will need to reference parent.window. The ribbon workbench 'how-to' article that shows starting a dialog from a ribbon button does infact use openStdWin to ensure consistency with the out of the box dialog experience. I have updated the code to use the parent window when required. Footnotes There are a couple of other notable aspects of Turbo Forms that I thought I'd point out: IFRAMES that are collapsed by default are not sized correctly. If you have an IFRAME or HTML Webresource inside a Tab that is collaposed by default you will find that they are not sized correctly when the tab is expanded. This will be fixed in an upcoming update but until then you will need to show the tab by default and collapse when the form is loaded. entityType vs typename Turbo Forms have dropped the typename attribute of Lookup values. In the past, the following code would return the same: Xrm.Page.getAttribute("parentcustomerid").getValue()[0].typename Xrm.Page.getAttribute("parentcustomerid").getValue()[0].entityType With Turbo Forms only the documented entityType is available. The typename attribute was left over from the CRM4 days and just had not been removed until now! @ScottDurow  

Introducing SparkleXRM Metadata Server

Speed up your HTML web resources by caching metadata such as localised field labels and options sets. If you've developed an HTML web resource for Dynamics CRM that includes field labels, option sets or any other element that is stored in the Dynamics CRM metadata then you’ll know about the delay each time the your UI is rendered whilst information is downloaded from the server. You could of course hard code this information in your JavaScript but you'd suffer higher maintenance costs especially when supporting multiple languages. The SparkleXRM Metadata Server allows dynamic expressions to be included in JavaScript Web Resources that are evaluated on the server and then cached on the client side. /metadata var fieldLabel = <@contact.fullname.DisplayName@>; metadata/ This will output and cache the following on the client (for an LCID of 1033): var fieldLabel = "Full Name"; Learn more about the SparkleXRM Metadata Server!

Building a Refreshed Connection UI using SparkleXRM

I've now published all 5 videos in this series.  If you find yourself needing to create HTML Webresource in Dynamics CRM then I'm sure you will find something here of interest. Part 5 shows how to use the new SparkleXRM Metadata Server that I'll be publishing a post on very soon. Part 1 - Creating your first SpakleXRM Project Part 2 - View Model Form Data Binding & Unit Testing Part 3 - Adding an Editable Grid Part 4 - Pulling it all together Part 5 - Adding multi-language support Have fun! @ScottDurow

Building Rich UI Extensions for Dynamics CRM using SparkleXRM

I've added the first 3 videos in a 5 part series called 'Building Rich UI Extensions for Dynamics CRM using SparkleXRM' Part 1 - Creating your first SpakleXRM Project Part 2 - View Model Form Data Binding & Unit Testing Part 3 - Adding an Editable Grid Part 4 - Pulling it all together Part 5 - Adding multi-language support   Have fun! @ScottDurow

Can I do that (in Dynamics CRM) ?

I'm sure by now that you've seen the new hierarchical visualisations in Dynamics CRM 2015. By clicking on the little icon in lists or on a form you can see the records graphically laid out. In true Dynamics CRM style anything you can do through the user interface is accessible through the SDK and so we now have the ability perform fetchXml queries using the above, eq-or-above, under & eq-or-under conditions. These new search criteria will find records up to a maximum of 100 recursions for a single hierarchical relationship. Take a look at the excellent SDK topic Query hierarchical data on the subject. I have found that when some users see the cool looking Dynamics CRM Online logon page they will ask 'Can I do that?!' I thought I would answer that question with a new SparkleXRM sample solution. Take a look:

Installing Network Visualisations (CRM 2015)

Import SparkleXRM - Import NetworkView -

Usual MIT license applies!

Known Issues For a list of known issues and reporting new ones please use the GitHub repository.Thanks to CRMCAT and Jukka Niiranen for all the help and feedback so far. Have Fun! @ScottDurow