Script Load Dependencies in Version 9

A long time ago, Dynamics CRM introduced the concept of asynchronous loading of form web resources – this created a challenge when scripts depend on other scripts to be loaded first (e.g. inheritance or using a common type system library during script loading). Version 9 has introduced an interesting feature where you can define the dependencies that a specific script has on other scripts. Imagine you had 3 scripts C.js requires B.js to load B.js requires A.js to load You can now define these dependencies in the web resources dialog:

I was hoping that by defining this dependency graph, the runtime would load them in the correct order like a module loader would – but having run some test the execution order still depending on the download speed and size of the script.

Script load execution order C - B - A

Script load execution order A - B - C

Conclusion The Web resource dependency feature is awesome when you have many resources that are required during form events at runtime (e.g. onload, onchange etc.) You can simply add the single script into the form and the other dependencies will be loaded for you. At this time, it's not a solution for where you need those dependencies during script load execution.

executionContext hits the big time!

You've seen the executionContext in the event registration dialog and you might even have used it on occasion. Well with the release of Dynamic 365 Customer Engagement Version 9, it has been elevated to be the replacement for Xrm.Page. The document describing the replacement for Xrm.Page details it as ExecutionContext.getFormContext – due to the capitalisation of ExecutionContext it implies that this is a global object, when in fact it must be passed as a parameter to the event handler by checking 'Pass execution context as first parameter' checkbox.

Oddly - It's still unchecked by default given its importance!

So why the change? Imagine that we want to create a client side event on the Contact entity that picks up the parent account's telephone number and populates the contact's telephone when 'Use Account Phone' is set to Yes. We add the event code to both the form field on change and the editable grid on change for the 'Use Account Phone' field. If we were to use the 'old' Xrm.Page.getAttribute method –it would work on the form but it wouldn't work within the grid on change event handler. This is where the executionContext shines – it can provide a consistent way of getting to the current entity context irrespective of where the event is being fired from (form or grid).

Show me the code!

The following event handler is written using typescript – but it's essentially the same in JavaScript without the type declarations. The important bit is that the executionContext is defined an argument to the event handler and attribute values are retrieved from the context returned by it's getFormContext() method.

static onUseCompanyPhoneOnChanged(executionContext: Xrm.Page.EventContext) { var formContext = executionContext.getFormContext(); const company = formContext.data.entity.attributes.get<Xrm.Page.LookupAttribute>("parentcustomerid"); const usePhone = formContext.data.entity.attributes.get<Xrm.Page.BooleanAttribute>(dev1_useaccounttelephone); const parentcustomeridValue = company.getValue();

// If usePhone then set the phone from the parent customer
if (usePhone.getValue() &&
    parentcustomeridValue != null &&
    parentcustomeridValue[0].entityType === "account") {
    const accountid = parentcustomeridValue[0].id;
    Xrm.WebApi.retrieveRecord("account", accountid, "?$select=telephone1")
        .then(result =&gt; {
            formContext.data.entity.attributes.get("telephone1").setValue(result["telephone1"]);
        });
}

}

Some Additional Notes: All the attributes that are used in the event must be in the subgrid row (parent customer attribute in this case). You can access the parent form container attributes usingparent.Xrm.Page.getAttribute("name").getValue() Xrm.Page still works in Version 9 but it's a good idea to start thinking about giving executionContext the attention it deserves! Hope this helps!

Solution Packager and global optionset enum support in spkl Task Runner

I’ve published version 1.0.9 of spkl to NuGet - this adds the following new features:

Global optionset enum generation for early bound classes. Solution Packager support

Global Optionset enum generation This was a tricky one due to the CrmSvcUtil not making it easy to prevent multiple enums being output where a global optionset is used, but you can now add the following to your spkl.json early bound section to generate global optionset enums. { "earlyboundtypes": [ { ... "generateOptionsetEnums": true, ... } ] }

In a future update, I’ll add the ability to filter out the enums to only those used. Solution Packager Support The solution packager allows you to manage your Dynamics metadata inside a Visual Studio project by extracting the solution into separate xml files. When you need to combine multiple updates from code comments, you can then use the packager to re-combine and import into Dynamics. To configure the solution packager task you can add the following to your spkl.json /* The solutions section defines a solution that can be extracted to individual xml files to make versioning of Dynamics metadata (entities, attributes etc) easier / "solutions": [ { "profile": "default,debug", / The unique name of the solution to extract, unpack, pack and import / "solution_uniquename": "spkltestsolution", / The relative folder path to store the extracted solution metadata xml files / "packagepath": "package", / Set to 'true' to increment the minor version number before importing from the xml files */ "incrementonimport": false } ]

There are two .bat files provided that will call: spkl unpack This will extract the solution specifed in the spkl.json into the packagepath as multiple xml files spkl import This will re-pack the xml files and import into Dynamics - optionally increasing the version number of the solution to account for the new build.

Continuous Integration using spkl Task Runner

This is the third video in a series showing you how to quickly setup VSTS Continuous Integration with spkl.

Watch in youtube 1. Learn more about the spkl task runner 2. Learn how to deploy plugins with the spkl task runnner 3. Learn how to deploy webresources with the spkl task runnner

Deploying Webresources using spkl Task Runner

This is the second video in a series showing you how get up and running with spkl with no fuss!

Watch in youtube 1. Learn more about the spkl task runner 2. Learn how to deploy plugins with the spkl task runnner

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.

There is something rather different about Dynamics 365 Business Process Flows!

The new business process flow designer in Dynamics 365 is lovely! However, I'm not going to talk about that since it's rightly had lots of love by others already. For me the biggest change in Dynamics 365 is the fact that running Business Process Flows (BPFs) are now stored as entity records. Instance details are no longer held as fields on the associated record. I first visited this topic back in the CRM2013 days with the introductions of Business Process Flows where I described how to programmatically change the process. Previously when a BPF was started, all of the state about the position was held on the record it was run on was stored in fields on the record itself: Process Id: The ID of the BPF running Stage Id: The ID of the BPF step that was active Traversed Path: A comma separated string listing the GUIDs of current path of steps taken through the BPF. This is to support BPFs with branching logic. With the new Dynamics 365 BPFs, each process activated is automatically has an entity created that looks just like any other custom entity. The information about the processes running and any record is now stored as instances of this entity with a N:1 relationship to the parent record and any subsequent related entities. This BPF entity has similar attributes that were stored on the parent entity, but with the following additions: Active Stage Id: The ID of the BPF step that is active – replaces the Stage Id attribute. Activate Stage Started On: The Date Time that the current step was started on – this allows calculation of the amount of time it has been active for State & Status: Each BPF Instance has its own state that allows finishing and abandoning before other BPF are run.

  In addition to making migration of data with running BPFs a little easier - this approach has the following advantages: You can control access to BPFs using standard entity role privileges You can have multiple BPFs running on the same record You can see how long the current stage has been active for You can Abandon/Finish a BPF BPF Privileges Prior to Dynamics365, you would have controlled which roles could access your BPF using the Business Process Flow Role Check list.     In Dynamics 365 when you click the 'Enable Security Roles' button your BPF you are presented with a list of Roles that you can open up and define access in the 'Business Process Flow' tab:

Multiple BPFs on the same record

Switching BPFs no longer overwrites the previous active step – meaning that you can 'switch' back to a previously started BPF and it will carry on from the same place. This means that BPFs can run in parallel on the same record. If a user does not have access to the running BPF they will see the next running BPF in the list (that they have access to). If the user has no access to any BPF that is active – then no BPF is shown at all. If user has read only access to the BPF that is running, then they can see it, but not change the active step. When a new record is created, the first BPF that the user has create privileges on is automatically started. When you use the Switch Process dialog, you can now see if the Business Process Flow is already running, who started it and when it was run.

NOTE: Because the roles reference the BPF entities – you must also include the system generated BPF entities in any solution you intend to export and import into another system.

Active Step timer Now that we have the ability to store addition data on the running BPF instance, we have the time that the current step was started on. This also means that when switching between processes, we can see the time spent in each step in parallel running BPFs.

Abandon/Finish

Since each BPF has its own state fields, a business process can be marked as Finished – or Abandoned at which point it becomes greyed out and read only.

When you 'Abandon' or 'Finish' a BPF it is moved into the 'Archived' section of the 'Switch Process' dialog.
NOTE: You might think that this means that you could then run the BPF a second time, but in-fact it can only have a single instance per BPF – and you must 'Reactivate' it to use it again.

Reactivating an Abandoned BPF will start at the previously active step Reactivating a Finished BPF will start it from the beginning again. Example Imagine your business has a sales process that requires an approval by a Sales Manager. At a specific step in that sales process you could run a workflow to start a parallel BPF that only the Sales Managers have access to. When they view the record, making the Approval BPF higher in the ordered list of BPFS will mean that they will see the Approval BPF instead of the main Sales Process. They can then advance the steps to 'Approved' and mark as Finished. This could then in turn start another Workflow that updates a field on the Opportunity. Using this technique in combination with Field Level Security gives a rather neat solution for custom approval processes. When I first saw this change I admit I was rather nervous because it was such a big system change. I've now done a number of upgrades to Dynamics 365 and the issues I found have all been resolved. I'm really starting to like the new possibilities that Parallel BPFs brings to Dynamics 365. @ScottDurow