Sunday, January 20, 2019

Create a link to a new UI form

I was reading recently in a D365 CE discussion thread that someone wanted to create an email using a workflow, and the email needed to have a link to an Account form in the new UI.

This is possible if you know how to make URL parameters appear the way you want in a workflow email. Consider this: if you try to create a link in the email using the editor, and you click on the Link icon, then you do not have any options to add a reference to a record’s Global Unique ID (GUID) in the URL:


Our goal is to make a URL that contains the parameters needed to trick CE into showing the new UI form when the user clicks the link to access the account.

The URL we are trying to create takes this form:

…//xxxx.crm.dynamics.com/main.aspx?appid=&pagetype=entityrecord&etn=account&id=

Where:

    “xxxx.crm.dynamics.com/main.aspx?” is your base URL
    “appid=” is the parameter that navigates the user to the new UI
    “pagetype=entityrecord&etn=account&id=” will open the desired account record

The base URL seems easy. However, if you are following best practices, then you know it is not a good idea to hard code the base URL into your workflows. The reason is because most people have a 3 phase process to Develop a solution, test it in a Staging environment, and then deploy it into Production. Each one of those environments has its own URL. I solved that problem by creating a workflow Action in all 3 environments that holds the base URL. More on this later.

To get the App ID, open your app designer and get the GUID of the app. It follows the “/” and ends at the “#”


Now I am ready to create an Action to assemble the URL we want. I put an “aaaaa_ ” in the front of the name to make it appear at the top of the list just as an illustration for this article. 
 In that Action, I created a couple arguments for input and output. The first one is an input parameter with the Account GUID (we will get to how we get the GUID in a minute). The second argument will hold the return value.

Next, add a step to assign the return value with the base URL from above.







The second step in the action appends the necessary account parameters to the previous step. This will give us a complete URL when it is called. I could have done this all in one URL, but in best practice, I would have made the system URL a separate Action that is not promoted with my development solution and lives only in my Development, Staging and Production system so that I do not have any hard coded URLs in my workflows.


 Now when we call that Action, we need to pass in the Account GUID as a string. The solution I found was to use a free solution called Workflow Elements by Aiden Kaskela. This solution has the ability to reveal Metadata about the workflow as string values. After you download and import the solution to your system, you get some new options when you add steps to your workflows. The one we are interested in is the “Workflow – Get Metadata” which will provide the GUID of the record that triggered the workflow to start.

 


Next I created a workflow to create my email. The first step is set to run the Get Metadata feature provided by Workflow Elements. It does not take any parameters to configure. In subsequent steps in the workflow, it provides the Record ID of the account record that triggered the workflow to start.  


The second step in the workflow is to call my “aaaaa_create url to hub” action where I pass with the Account GUID as the input parameter.

The final step is to create the email that uses the EntityURL created by the previous step in the workflow and it provides just the Output parameter from the action, which contains the full URL we need.


When you run the workflow, it will now generate a full URL link to the related account for the new UI.
 

Leave me a note below if you found this useful.

Sunday, December 2, 2018

Customizing D365 forms using JavaScript

I know, a lot of people have written about customizing CRM forms with JavaScript, but I am learning some cool stuff and wanted to share what I learned this week.
The big news for me was that Promises are supported in D365 forms now. I am sure this is not news to many people, and to others they have no idea what I am talking about, so this article is for them.
Why are Promises important?
If you have written a JavaScript function that uses a “call back” (passing a function name as a parameter into another function), then you have probably run into the fact that the call back can happen at any time. If you have several of them that need to be run in a sequence, they will sometimes cause your code to fail because it does not execute them synchronously.
I have seen many programmers try to solve this problem by building “Christmas tree” code that nests one function inside the other until you are 15 levels deep in brackets, and lord help you if you if there is a syntax error with one bracket out of place. Even worse is the difficulty to test and maintain all permutations of “Christmas tree” code so that you are sure there are no errors. Promises are an excellent solution to that problem.
A Promise design pattern is way to write a function that will leverage the asynchronous nature of JavaScript with the ability to sequentially perform a series of tasks. 
I learned about Promises from a Pluralsight course authored by Jonathan Mills called JavaScript Best Practices. I did some research and found a few code samples in GitHub for CRM projects that used Promises. Here are some links that I used to learn more, but frankly, some of it was deeper than I needed.
Promises
https://blogs.msdn.microsoft.com/ie/2011/09/11/asynchronous-programming-in-javascript-with-promises/
Promise API framework for CRM
https://code.msdn.microsoft.com/CRM-Web-API-Functions-and-87cd0b45#content
It uses https://github.com/stefanpenner/es6-promise
https://github.com/mariusso/WebAPI.REST.js/releases




Some of the above links say that you need to include the e6promise.js library, and that may have been necessary in earlier versions of CRM, but I am working in V9.1 and it is not necessary to add any other framework to your project, but it did help me understand what is going on.
What got me started on this article was when I needed to build a customization and realized that I needed several sequential calls to fetch data first, then create new records, but they had to be executed in order.
I noticed that Jason Lattimer’s CRM REST Builder used a Promise syntax when I used the Xrm.WebApi option to build a request for fetching data, so I decided to see if I could make that work for me. Besides, I like the succinct format of WebAPI over the XMLHTTP format.
I created a form script called Library.js and in following best practices, created a FormLib namespace so all my methods and properties are prefixed with “FormLib.”.
First I used CRM REST Builder to create an asynchronous call to get some data for me that looks like this:
Xrm.WebApi.online.retrieveMultipleRecords("tn_changeorder", "?$select=tn_changeorderid&$filter=statuscode eq 0 and  _tn_quoteid_value eq <giud>").then(
     function success(results) {
         for (var i = 0; i < results.entities.length; i++) {
             var tn_changeorderid = results.entities[i]["tn_changeorderid"];
         }
     },
     function(error) {
         Xrm.Utility.alertDialog(error.message);
     }
);
Notice the “then” that follows the async call – this was my clue that the Xrm.WebApi was a Promise.
Following Jonathan Mills instructions, I created a wrapper function :
FormLib.GetChangeOrder = function () {
     return new Promise(function (fulfill, reject) {
         // begin REST code

        // end REST code
     });
};
and then I inserted the “fulfill” and “reject” into the REST code, and put it all together so that now my code looks like this:
FormLib.GetChangeOrder = function () {
     return new Promise(function (fulfill, reject) {
         // begin REST code
         Xrm.WebApi.online.retrieveMultipleRecords("tn_changeorder", "?$select=tn_changeorderid&$filter=statuscode eq 0 and  _tn_quoteid_value eq  <guid>" ).then(
             function success(results) {
                 for (var i = 0; i < results.entities.length; i++) {
                     var tn_changeorderid = results.entities[i]["tn_changeorderid"];
                 }
                fulfill();
             },
             function (error) {
                 Xrm.Utility.alertDialog(error.message);
                 reject();
             }
         );
         // end REST code
     });
};

Now every time I make an async call, I create one of these functions (above) and can fire them sequentially using a syntax that looks like this:
FormLib.GetChangeOrder()
            .then(FormLib.CreateRelatedCase)
            .then(FormLib.SetupDetails)
The magic is the fulfill() that calls the next item in the “then-chain”. The reject() allows you to call an error handler and gracefully exit the chain. In my example above, the “.then(FormLib.CreateRelatedCase)” is passed into GetChangeOrder() and executed after it has completed its task of looking for an existing record.
You could argue that it is easier to just call the next function in the chain by using the specific function name instead of calling fulfill(), but then you would have tight coupling and it is difficult to maintain when you have to decipher the code to figure out what the chain is.
Promises solves the problem of deep nesting of functions by splitting them all out to discrete, re-useable, loosely coupled, and testable functions that can be called sequentially. The Promise Design Pattern also makes handling errors and parallel tasks easier to manage. I recommend you learn this design pattern if you are going to do any amount of JavaScript coding.