The objective of this chapter is to explore the advanced customizations that can be applied to Dynamics 365. This includes implementing complex business processes with plugins and custom workflow activities. Also, you will learn how you can deploy these using the SPKL Task Runner, which was discussed in Chapter 2. Finally, you will also look at querying data using the Web API endpoints.
Getting Ready
To start with advanced customizations, you must first create the early bound types and include them in the Visual Studio project. You can create a separate Dynamics 365 solution to anchor the advanced customizations but you could also include them in the base solution. Having a single solution makes it simple to eliminate any complexities down the line. When it comes to plugin and custom workflow development, you can either use early-bound types or late-bound methods. The primary benefit of using early-bound types is that this eliminates typos when it comes to using attributes, making your code less prone to errors. Plus, this allows you to use LINQ queries, speeding up the development process. Additionally, this allows you to keep your code simple. There are several ways to generate early-bound types.
For this book, we will be using the Early Bound Generator plugin of the XrmToolBox. You can simply install it from the plugin store of the toolbox. See Figure 5-1.
Creating the Plugin
Let’s look at how this plugin can be used to generate the early-bound entity types. First, establish the connection with the Dynamics 365 instance. Once you’re connected successfully and open the Early Bound Generator plugin, you will be directed to the screen shown in Figure 5-2.
You must make sure you enter the correct namespace name for the project in which you are going to use the entity classes. If you click the Create All button, you can create all the entities, option sets, and actions at one time. Or you can create them individually by going into each tab (Entities, Option Sets, and Actions) and clicking the Create Entities/Option Sets/Actions button on each tab, which will generate the relevant class files. The generated files will be located in the folder shown in Figure 5-3.
Now you can add these files to the project, as illustrated in Figure 5-4. As you can see, all the namespaces are set as SBMA.Plugins.
So, let’s look at the requirements for SBMA. When a new member is created, a subscription must be created based on the membership type (Platinum, Gold, Silver, and Bronze). This action should be automated so the subscription record and relevant payment record are created behind the scenes swiftly so that when the user goes in for the verification, the records are there. Figure 5-5 shows the high-level business process.
We will show you a quick trick to make the plugin development easier. If you have Visual Studio 2015 installed, install the Dynamics CRM Developer Toolkit and create a Dynamics 365 plugin project. Navigate to the plugins folder, and you will see the PluginBase.cs class. As part of Microsoft best practices, this particular class will give you a wealth of resources to improve your plugin development. Include it in your project and make sure you change the namespace. Then, when you write the plugin, you can extend your plugin from the PluginBase class. Remember, you do not have to use fancy patterns when writing plugins; just stick to the basic code principles and always try to keep it simple.
The plugin code will create only the Member Subscription record. Creating the payment record will be done through a Dynamics 365 action. You can code the payment record creation in the plugin, but actions, as explained earlier, reduce the amount of coding you have to do. You will learn how to create an action to automatically create the Member Payment record through the plugin later in the chapter. See Figure 5-6, the PluginBase.cs class is added to the Plugin Project.
Let’s kick off the development by creating the MemberPlugn.cs file, which will extend the PluginBase.cs file, as shown here:
As per the requirements, you will first need to retrieve the member subscription type the user has selected. The following code segment retrieves it by passing the GUID of the new membership record created:
To get the newly created ID of the membership record, you will have to get the post-image of the record. The post-image and pre-image of a record are useful in updates. A pre-image can be described as a snapshot of the attributes of a record before the core operations. Similarly, a post-image can be described as a snapshot of the entity attributes after the core operations. As shown in Table 5-1, the availability of the pre- and post-images differs within the execution pipeline.
Table 5-1
Plugin Event Pipeline and Image Availability
Message
Stage
Pre-Image
Post-Image
Create
PRE
No
No
Create
POST
No
Yes
Update
PRE
Yes
No
Update
POST
Yes
Yes
Delete
PRE
Yes
No
Delete
POST
Yes
No
In this case, the plugin is fired after creating the membership record, which will get you the record after creating it. So, you will update the code file, as shown here:
After obtaining all the required data, you are now in a position to create the related subscription record. The following code creates the Subscription record:
//Calling the organization service to create the new member subscription
organizationService.Create(membersubscription);
}
You can see that you call GetMembershipTypeOfMember in this method. This creates the member subscription. You need to define the membership type as well. Finally, you need to call this method in the main execution method, as shown here:
Now that you have completed coding the plugin, you must deploy it. You will be using the SPKL Task Runner for the deployment. Install it in your project, as demonstrated in an earlier chapter. To deploy the plugin via SPKL, you must add a few attributes to your code, as shown here:
As you can see, we have set these attributes to deploy our plugin as a synchronous plugin, and the plugin message is Create. Since this is executed after the Membership record is created, it is set as a Post Create plugin. As discussed earlier, you need a post-image, which is the record that is created and that defines the attributes for the post-image, which will be returned to your code. After setting up these attributes, connect to the Dynamics 365 instance with the SPKL Task Runner by executing the deploy-plugins.bat command. To learn more about plugin deployment with the SPKL Task Runner, refer to https://www.develop1.net/public/post/2017/05/12/Deploying-Plugins-using-spkl-Task-Runner.
Figure 5-7 shows the membership being created. When the membership record is created, the relevant subscription will be created as well, as shown in Figure 5-8.
You can do many things with this process. For instance, when the subscription is created, until it is paid, you could trigger a workflow that waits until the due date and sends an e-mail to the member saying the subscription is not paid. The workflow will stop if the subscription status is set to Paid. Another scenario would be to set the subscription status to Paid if the related payment is completed. The takeaway from this is that no matter how complex the scenario is, you can implement it using these advanced customizations of Dynamics 365.
You will need to investigate the other side of this on your own. If you do not map your processes correctly, it will be maintenance nightmare and will have a big impact on the performance. Even though you have a lot of flexibility to extend the application, you need to use that flexibility with care.
Creating Custom Workflow Activities
In this section, you will learn how to write a custom workflow activity to implement complex business processes. As part of the scenario discussed in the previous section, now you must create the payment records to track the payments. To complete the process, a workflow should be triggered behind the scenes to create the payment record as soon as the subscription record is created. This workflow should then wait for seven days from the date the payment record is created and send an e-mail reminder to the primary contact of the business to pay the membership fee.
This workflow will be triggered when the member subscription record is created, and the custom workflow activity will be triggered to create the payment record. You need a custom workflow activity here, because you have to determine the payment method defined on the membership record. Remember, only one level of entity relationship is available to access from a standard workflow. Similarly, when sending the e-mail, you need the e-mail address of the primary contact of the member.
To begin creating the workflow, let’s first create the parent workflow. We discussed the details of how to create a workflow in the previous chapter. In this example, we will also demonstrate the use of input and output variables.
To begin writing the workflow activity, you will be using early-bound classes. Follow the steps to generate the early-bound classes described earlier. You need to generate it again, because the assembly for the workflow activity is different, in this case, SBMA.Workflow. In the XrmToolBox, change the assembly name as required, generate the entity reference classes, and add them to the project. See Figure 5-9.
As shown next, after setting this up, add the workflow activity class to your project:
To use the Microsoft.Xrm.Sdk.Workflow library, you must install it from NuGet. Get the latest version from https://www.nuget.org/packages/Microsoft.CrmSdk.Workflow/. Also, as we did with plugins, we will be using the WorkflowActivityBase class that was generated and the CodeActivity class, which is the parent class of the custom activity and which is a child class of System.Activities.CodeActivity.
One of the cool things about workflow activities is that you can pass parameters to the activity and return values from it using out arguments. For this activity, you must pass the Member reference, which is the owner of the subscription created. With this reference, you can determine the preferred payment method of the member. Let’s code.
For this workflow activity, you must pass the member reference and subscription reference. You can see from the following code that the two input variables are declared:
[Input("Member")]
[ReferenceTarget("account")]
public InArgument<EntityReference> InMember { get; set; }
[Input("MemberSubscription")]
[ReferenceTarget("sbma_membersubscription")]
public InArgument<EntityReference> InMemberSubscription { get; set; }
To create the member payment record, you will require the payment due amount, payment due date, payment method, and member subscription reference. The following code illustrates the methods required to get this information:
We will be using the SPKL Task Runner to deploy the custom workflow activity; therefore, we have installed the SPKL Task Runner to the workflow project and set the attributes for the workflow activity as we did for the plugins. The completed code should look something like this:
The next step is to run the deploy-workflows.bat command of the SPKL Task Runner to install the workflow activity. Once it’s installed, you can see the custom workflow activity when the Add Step drop-down is expanded. See Figure 5-10.
When adding the step to the workflow, you must set the two parameters as illustrated in Figure 5-11.
When the workflow is executed, the payment record will be created based on the membership and the member subscription information.
Calling Custom Actions from JavaScript
In this section, let’s look at how you can call an action using JavaScript and the Web API. The following code can be used externally to create records in Dynamics 365. This approach is extremely useful in scenarios where you allow external programs to interact with the application. In this example, you will look at applying for membership with the organization. First let’s create the action shown in Figure 5-12. This action has a set of parameters that could include the fields of the external application, and once the data is submitted, an applicant record in Dynamics 365 will be created.
The following is the JavaScript code that calls the action. The function callCustomAction is a common function that can be used to call any action in Dynamics 365.
function submitApplication()
{
var actionName = "sbma_SubmitApplication";
// Define the input parameters
var inParams = {
"Topic" : ("#Topic"),
"FisrtName" : ("#FisrtName"),
"LastName" : ("#LastName"),
"CompanyName" : ("#CompanyName"),
"BuisnessPhone" : ("#BuisnessPhone"),
"Email" : ("#Email"),
"AnnualRevenue" : ("#AnnualRevenue")
};
var actionResponse = callCustomAction(actionName, inpParams);
Again, this is a simple example. Most importantly, there are many other ways to achieve the same functionality within the Dynamics 365 ecosystem, and choosing the one best suited to achieving the project objectives must done with great care.
Summary
This chapter covered the implementation of complex business logic with plugins and custom workflow activities. In the next chapter, you will be taking the implementation a little bit further by integrating Dynamics 365 with Azure.