Tag Archives: Id

Microsoft Dynamics 365: Notifications Using JavaScript

In Microsoft Dynamics 365, sometimes we need to send automated notifications to end users. These notifications can come from the server (i.e. back-end automation using workflows, plugins, etc) or from the code loaded in the user’s web browser (i.e. front-end or client side automation using JavaScript). The latter notifications will make up the scope of this blog post. We will cover form level notifications (with and without persistence), field level notifications and popup boxes notifications using JavaScript.

Summary of the key syntax

Here is a high-level summary of the main Microsoft Dynamics 365 JavaScript notifications demonstrated in this blog post.

  • Form Level Notifications – Set Notification
    formContext.ui.setFormNotification(message, messageType, uniqueId);
  • Form Level Notifications – Clear Notification
    formContext.ui.clearFormNotification(uniqueId);
  • Field Specific Notifications – Set Notification
    formContext.getControl(fieldLogicalName).setNotification(message, uniqueId);
  • Field Specific Notifications – Clear Notification
    formContext.getControl(fieldLogicalName).clearNotification(uniqueId);
  • Alert Box
    alert(message);
  • Confirmation Box
    confirm(message);
  • Prompt Box
    prompt(message, sampleText);

Form Level Notifications

Here is an example of form level notifications applied to the Contact entity’s form. The notification options available at form-level are: Error, Warning and Information. These notification options have different icons as shown in the image below.
Page Level Notification

Below is the JavaScript code that was used to generate the notifications shown in the image above. Therefore, every time a user opens up a contact form, these notifications will always appear at the top of the form.

function FormLevelNotification(executionContext) {
    var formContext = executionContext.getFormContext();    
    formContext.ui.setFormNotification("Example of an ERROR notification. ", "ERROR");
    formContext.ui.setFormNotification("Example of a WARNING notification. ", "WARNING");
    formContext.ui.setFormNotification("Example of an INFORMATION notification.", "INFO");    
}

Instead of having persistent notifications (ever present whenever a user opens the contact form), it is commons for organizations to implement a modified version of these notifications i.e. where the notifications above expire after a specifies amount of time. Therefore, every time a user opens a contact form (or any other form where this functionality is implemented), they get notifications similar to image above, but after a specified amount of time, the notifications disappear and user end up with form like the one below.
Page Level Notification Expired

This modified option where the form level notifications disappear after a specified amount of time can be accomplished using the code below. In code below, I have chosen an expiration time of 30 seconds. Therefore, the form level notifications would only persist for the first 30 seconds after a user opens up a contact form.

function FormLevelNotificationWithExpiration(executionContext) {
    var formContext = executionContext.getFormContext();
    var notificationTime = 30000; // 30 seconds in milliseconds 
    var errorId = "error";
    var warningId = "warning";
    var infoId = "info";
    //Set notifications
    formContext.ui.setFormNotification("Example of an ERROR notification. ", "ERROR", errorId);
    formContext.ui.setFormNotification("Example of a WARNING notification. ", "WARNING", warningId);
    formContext.ui.setFormNotification("Example of an INFORMATION notification.", "INFO", infoId);

    //Clear the notifications after the specified amount of time time e.g. 5 seconds
    setTimeout(
        function () {      
            formContext.ui.clearFormNotification(errorId);
            formContext.ui.clearFormNotification(warningId);           
            formContext.ui.clearFormNotification(infoId);
        },
        notificationTime
    );
}

Field Specific Notifications

To guide users in completing a form correctly, you can provide field specific notification like the ones below. The example below shows the subscription section on the Contact entity’s form. Logically, the Subscription Start Date must precede the Subscription End Date. Whenever a users enters a Subscription End Date that precedes the Subscription Start Date, the field level notifications appear advising the user that “The Subscription End Date cannot be before Subscription Start Date” as show below.
Field Level Notifications

The functionality shown in the image above was accomplished using the following JavaScript functions.

//Validation of the TV Subscription Dates
function TvSuscriptionDateValidation(executionContext) {
    var formContext = executionContext.getFormContext();
    var tvSubStartDateLogicalName = "hos_tvsubstartdate";
    var tvSubEndDateLogicalName = "hos_tvsubenddate";
    var startDateField = formContext.getAttribute(tvSubStartDateLogicalName);
    var endDateField = formContext.getAttribute(tvSubEndDateLogicalName);
    var endDateFieldControl = formContext.getControl(tvSubEndDateLogicalName);
    var startDate, endDate;

    if (startDateField != null && endDateField != null) {
        startDate = startDateField.getValue();
        endDate = endDateField.getValue();
        if (IsDate(startDate) && IsDate(endDate) && startDate > endDate ) {
            //Display an error message if the dates entered are logically invalid.
            endDateFieldControl.setNotification("The Subscription End Date cannot be before Subscritpion Start Date.", "tvEndDate");
            endDateField.setValue(null);
        }
        else {
            endDateFieldControl.clearNotification("tvEndDate");            
        }
    }
}

//Verify that the field contains date instead of a null value
function IsDate (input) {
    if (Object.prototype.toString.call(input) === "[object Date]") {
        return true;
    }   
    return false;
}

Popup Notifications

Sometimes you really to get the user’s attention, that is, prevent them from interacting with the form until they have acknowledged your message. To accomplish that endeavor using JavaScript, you can use the popup boxes. There are 3 types of popup boxes (i.e. alert box, confirmation box and prompt box). In this section, we will show what these popup look like in Dynamics 365 and provide an example of how to implement them.

Alert Box

Here is an example of an Alert Box in Dynamics 365. The user can acknowledge the message by pressing OK and proceed interact with the form.
Alert Box

The functionality shown in the image above was accomplished using the following JavaScript function.

function AlertBox() {
    alert("This is an example of a JavScript Alert window ");

    //Alternatively way of writing an Alert Box with the Window prefix:    
    //window.alert("This is an example of a JavScript Alert window ");
}

Confirmation Box

Here is an example of an Confirmation Box in Dynamics 365. The user is given two options. Depending on the user’s choice, you can proceed to add more logic. In this example, we use an alert box to notify user of the choice that was selected.
Confirmation Box

The functionality shown in the image above was accomplished using the following JavaScript function.

function ConfirmBox() {    
    var confirmationText;
    if (confirm("Would you like to proceed?")) {
        confirmationText = "You pressed OK!";
    } else {
        confirmationText = "You pressed Cancel!";
    }
    //Using the alert notification to show the option selected
    alert(confirmationText);

    //Alternatively way of writing an Confirm Box with the Window prefix:    
    //window.confirm("Press a button: 'OK' or 'Cancel'");
}

Prompt Box

Here is an example of an Prompt Box in Dynamics 365. The user is given a text box where they can enter an answer as well as two options (i.e. OK and Cancel). Depending on the user’s responses, you can proceed to add more logic. In this example, we use an alert box to notify user of the text that was entered, if they click on OK.
Prompt Box

The functionality shown in the image above was accomplished using the following JavaScript function.

function PromptBox() {
    var userText = prompt("Please enter your name below", "This is sample text ");
    //Using the alert notification to show the text entered in the prompt box
    alert("You said your name is: \n" + userText);   

    //Alternatively way of writing an Prompt Box with the Window prefix:
    //window.prompt("Please enter some text below", "This is sample text ");
}

Best Practices and Recommendations

For demonstration purposes in this blog post, I included the notification messages in the code. However, for easier maintenance and to give more flexibility to the end users, who may not be Dynamics 365 software developers, it is recommended to put the notification messages in the Dynamics 365 Configuration Data and then create JavaScript helper function(s) that retrieve the data at runtime using a key. Using this approach, end users with the appropriate security roles can update the JavaScript notification messages anytime without calling upon the services of a Dynamics 365 software developer with JavaScript experience.

Microsoft Dynamics 365: The Complete Guide to Getting and Setting Fields Using a Plugin

When extending the Microsoft Dynamics 365 platform, there is often a need to retrieve and/or set field values. In this post, we will cover how to get and set values for the Microsoft Dynamics 365/CRM platform fields using a plugin, developed using the Microsoft C# programming language. You can also develop plugins and perform the operations demonstrated in this post using other .Net platform-supported programming languages. In Dynamics 365, you can create the following types of fields (or datatypes): Single Line of Text, Option Set, MultiSelect Option Set, Two Options, Image, Whole Number, Floating Point Number, Decimal Number, Currency, Multiple Lines of Text, Date and Time, Lookup and Customer.

Plugin Set Up

Here is a plugin setup you can use to implement the field specific code in this post.

using System;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;

namespace ItsFascinating_Plugins_D365
{
    public class PreUpdateAccount : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            string pluginMessageUpdate = "update";
            Entity primaryEntity = new Entity();

            if (serviceProvider == null)
            {
                throw new ArgumentNullException("localContext");
            }                

            #region Plugin Setup Variables
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.InitiatingUserId);
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            #endregion
            #region Validation Prior Execution
            //Exist if plugin if it's not called at stage 20 of the excution pipeline
            if (context.Stage != 20)
            {
                tracingService.Trace("Invalid Stage: Stage = {0}", context.Stage);
                return;
            }
            //Exist if plugin if it called for any other operation other than Update 
            if (!context.MessageName.ToLower().Equals(pluginMessageUpdate))
            {
                tracingService.Trace("Invalid Message: MessageName = {0}", context.MessageName);
                return;
            }
            #endregion
            #region Plugin Logic
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                try
                {
                    primaryEntity = context.InputParameters["Target"] as Entity;


                    //INSERT THE FIELD SPECIFIC CODE BELOW HERE


                }
                catch(Exception ex)
                {                 
                    throw new InvalidPluginExecutionException(string.Format("Error occured in the PreUpdateAccount plugin: {0}", ex.Message));
                }
                
            }
            #endregion
        }
    }
}               

Field Specific Code

To use the field specific code below, in the plugin above, copy the code below and paste it below the line “//INSERT THE FIELD SPECIFIC CODE BELOW HERE”, in the Plugin Setup Code section.

Single Line of Text

Here is an example of a Single Line of Text field on a Dynamics 365 form:
Single Line of Text

Here is the C# code for getting and setting the value of a Single Line of Text field (Display Name: “Account Number” | Database Name: “accountnumber”):

//Get and Set Single Line of Text field value
// Display Name: "Account Number" | Database Name: "accountnumber"
string accountNumberFieldLogicalName = "accountnumber";
Object accountNumberObj;
string accountNumber;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(accountNumberFieldLogicalName, out accountNumberObj))
{
	//Get value of Single Line of Text field
	accountNumber = Convert.ToString(accountNumberObj);

	//Set value of Single Line of Text field
	primaryEntity[accountNumberFieldLogicalName] = "ACC-1000-TV-2019-ON";
}

Multiple Lines of Text

Here is an example of a Multiple Lines of Text field on a Dynamics 365 form:
Multiple Lines of Text

Here is the C# code for getting and setting the value of a Multiple Lines of Text field (Display Name: “Description” | Database Name: “description”):

//Get and Set Multiple Lines of Text field value
// Display Name: "Description" | Database Name: "description"
string descriptionFieldLogicalName = "description";
Object descriptionObj;
string description;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(descriptionFieldLogicalName, out descriptionObj))
{
	//Get value of Multiple Lines of Text field
	description = Convert.ToString(descriptionObj);

	//Set value of Multiple Lines of Text field
	primaryEntity[descriptionFieldLogicalName] =
		"To be, or not to be, that is the question: \n" +
		"Whether \'tis nobler in the mind to suffer \n" +
		"The slings and arrows of outrageous fortune, \n" +
		"Or to take Arms against a Sea of troubles, \n" +
		"And by opposing end them: to die, to sleep; \n" +
		"No more; and by a sleep, to say we end \n" +
		"The heart-ache, and the thousand natural shocks \n" +
		"That Flesh is heir to? \'Tis a consummation \n" +
		"Devoutly to be wished.To die, to sleep, \n" +
		"perchance to Dream; aye, there\'s the rub, \n" +
		"For in that sleep of death, what dreams may come, \n" +
		"When we have shuffled off this mortal coil, \n" +
		"Must give us pause.";
}

Whole Number

Here is an example of a Whole Number field on a Dynamics 365 form:
Whole Number field

Here is the C# code for getting and setting the value of a Whole Number field (Display Name: “Number of Employees” | Database Name: “numberofemployees”):

//Get and Set Whole Number field value
// Display Name: "Number of Employees" | Database Name: "numberofemployees"
string numberOfEmployeesFieldLogicalName = "numberofemployees";
Object numberOfEmployeesObj;
int numberOfEmployees;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(numberOfEmployeesFieldLogicalName, out numberOfEmployeesObj))
{
	//Get value of Whole Number field
	numberOfEmployees = Convert.ToInt32(numberOfEmployeesObj);

	//Set value of Whole Number field
	primaryEntity[numberOfEmployeesFieldLogicalName] = 120000;
}

Decimal Number

Here is an example of a Decimal Number field on a Dynamics 365 form:
Decimal Number field

Here is the C# code for getting and setting the value of a Decimal Number field (Display Name: “Exchange Rate” | Database Name: “exchangerate”):

//Get and Set Decimal Number field value
// Display Name: "USD/CAD Exchange Rate" | Database Name: "hos_usdcadexchangerate"
string exchangeRateFieldLogicalName = "hos_usdcadexchangerate";
Object exchangeRateObj;
decimal exchangeRate;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(exchangeRateFieldLogicalName, out exchangeRateObj))
{
	//Get value of Decimal Number field
	exchangeRate = Convert.ToDecimal(exchangeRateObj);

	//Set value of Decimal Number field
	primaryEntity[exchangeRateFieldLogicalName] = 1.312775;
}

Floating Point Number

Here are some examples of Floating Number fields on a Dynamics 365 form:
Floating Point Number field

Here is the C# code for getting and setting the value of a Floating Number field (Display Name: “Address 1: Longitude” | Database Name: “address1_longitude”):

//Get and Set Floating Point Number field value
// Display Name: "Address 1: Longitude" | Database Name: "address1_longitude"
string longitudeFieldLogicalName = "address1_longitude";
Object longitudeFieldObj;
float longitudeField;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(longitudeFieldLogicalName, out longitudeFieldObj))
{
	//Get value of Floating Point Number field
	longitudeField = Convert.ToSingle(longitudeFieldObj);

	//Set value of Floating Point Number field
	primaryEntity[longitudeFieldLogicalName] = -79.387054f;
}

Currency

Here is an example of a Currency field on a Dynamics 365 form:
Currency field

Here is the C# code for getting and setting the value of a Currency field (Display Name: “Annual Revenue” | Database Name: “revenue”):

//Get and Set Currency field value
// Display Name: "Annual Revenue" | Database Name: "revenue"
string revenueFieldLogicalName = "revenue";
Object revenueObj;
decimal revenue;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(revenueFieldLogicalName, out revenueObj))
{
 //Get value of Currency field                                               
 revenue = ((Money)revenueObj).Value;

 //Set value of Currency field
 primaryEntity[revenueFieldLogicalName] = new Money(10200500800.78m);
}

Two Options

Here are some examples of Two Options fields on a Dynamics 365 form:
Two Options field

Here is the C# code for getting and setting the value of a Two Options field (Display Name: “Email” | Database Name: “donotemail”):

//Get and Set Two Options field value
// Display Name: "Email" | Database Name: "donotemail"
string dontAllowEmailsFieldLogicalName = "donotemail";
Object dontAllowEmailsObj;
bool dontAllowEmails;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(dontAllowEmailsFieldLogicalName, out dontAllowEmailsObj))
{
	//Get value of Two Options field                                               
	dontAllowEmails = (bool)dontAllowEmailsObj;

	//Set value of Two Options field
	primaryEntity[dontAllowEmailsFieldLogicalName] = true;
}

Option Set

Here is an example of an Option Set field on a Dynamics 365 form:
Option Set field

Here is the C# code for getting and setting the value of an Option Set field (Display Name: “Contact Method” | Database Name: “preferredcontactmethodcode”):

//Get and Set Option Set field value
// Display Name: "Contact Method" | Database Name: "preferredcontactmethodcode"
string contactMethodLogicalName = "preferredcontactmethodcode";
Object contactMethodObj;
int contactMethod;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(contactMethodLogicalName, out contactMethodObj))
{
	//Get value of Option Set field 
	contactMethod = ((OptionSetValue)contactMethodObj).Value;

	//Set value of Option Set field
	primaryEntity[contactMethodLogicalName] = 3;
}

MultiSelect Option Set

Here is an example of a MultiSelect Option Set field on a Dynamics 365 form:
MultiSelect Option Set field

Here is the C# code for getting and setting the values of a MultiSelect Option Set field (Display Name: “Geographical Areas of Operation” | Database Name: “hos_geographicalareasofoperation”) :

//Get and Set MultiSelect Option Set field value
// Display Name: "Geographical Areas of Operation" | Database Name: "hos_geographicalareasofoperation"
string locationFieldLogicalName = "hos_geographicalareasofoperation";
Object locationFieldObj;
OptionSetValueCollection locationField;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(locationFieldLogicalName, out locationFieldObj))
{
	//Get the collection of value(s) for MultiSelect Option Set field
	locationField = (OptionSetValueCollection)locationFieldObj;

	//Set collection of value(s) for MultiSelect Option Set field (version 1 - single line implementation)
	primaryEntity[locationFieldLogicalName] = new OptionSetValueCollection(new List<OptionSetValue>() { new OptionSetValue(183840000), new OptionSetValue(183840001), new OptionSetValue(183840003), new OptionSetValue(183840006), new OptionSetValue(183840010) });

	//Set collection of value(s) for MultiSelect Option Set field (version 2 - multiple lines implementation)
	/*
	OptionSetValueCollection locationMultiOptionSet = new OptionSetValueCollection();
	locationMultiOptionSet.Add(new OptionSetValue(183840000));
	locationMultiOptionSet.Add(new OptionSetValue(183840001));
	locationMultiOptionSet.Add(new OptionSetValue(183840003));
	locationMultiOptionSet.Add(new OptionSetValue(183840006));
	locationMultiOptionSet.Add(new OptionSetValue(183840010));
	primaryEntity[locationFieldLogicalName] = new OptionSetValueCollection(locationMultiOptionSet);
	*/
}

Date and Time

Here are some examples of Date and Time fields on a Dynamics 365 form:
Date and Time field

Here is the C# code for getting and setting the value of a Date and Time field (Display Name: “Follow Up Date” | Database Name: “hos_followupdate”):

//Get and Set Date and Time field value
// Display Name: "Subscription Start" | Database Name: "hos_subscriptionstart"
// Display Name: "Subscription End" | Database Name: "hos_subscriptionend"
string subscriptionStartLogicalName = "hos_subscriptionstart";
string subscriptionEndLogicalName = "hos_subscriptionend";
Object subscriptionStartdObj;
DateTime subscriptionStart = new DateTime();

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(subscriptionStartLogicalName, out subscriptionStartdObj))
{
	if (subscriptionStartdObj != null)
	{
		//Get value of Date and Time field  
		subscriptionStart = Convert.ToDateTime(subscriptionStartdObj);

		//Set value of Date and Time field   
		primaryEntity[subscriptionEndLogicalName] = subscriptionStart.AddYears(1);
	}
	else
	{
		//If the Subscription Start is null, set the Subscription End as well
		primaryEntity[subscriptionEndLogicalName] = null;
	}
}

Lookup

Here is an example of a Lookup field on a Dynamics 365 form:
Lookup field

Here is the C# code for getting and setting the value of a Lookup field (Display Name: “Account Manager” | Database Name: “hos_accountmanager”) :

//Get and Set Lookup field value
// Display Name: "Account Manager" | Database Name: "hos_accountmanager"
string accountManagerLogicalName = "hos_accountmanager";
Object accountManagerObj;
EntityReference accountManager;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(accountManagerLogicalName, out accountManagerObj))
{
	if (accountManagerObj != null)
	{
		//Get value of a Lookup field and its attributes                                              
		accountManager = (EntityReference)accountManagerObj;
		Guid guid = accountManager.Id;
		string entityName = accountManager.LogicalName;
		string name = accountManager.Name;

		//Set value of a Lookup field and its attributes                        
		primaryEntity[accountManagerLogicalName] = new EntityReference("systemuser", new Guid("A6AF4DAB-10C4-E911-A2E2-005056AE4389"));
	}
}

Customer

Here is an example of a Customer field on a Dynamics 365 form:
Customer field

Here is the C# code for getting and setting the value of a Customer field (Display Name: “Main Customer” | Database Name: “hos_maincustomer”):

//Get and Set Customer field value
// Display Name: "Main Customer" | Database Name: "hos_maincustomer"
string mainCustomerLogicalName = "hos_maincustomer";
Object mainCustomerObj;
EntityReference mainCustomer;

//Check if the specified attribute is contained in the internal dictionary before you you try to Get its value
if (primaryEntity.Attributes.TryGetValue(mainCustomerLogicalName, out mainCustomerObj))
{
	if (mainCustomerObj != null)
	{
		//Get value of Customer field and its attributes                                              
		mainCustomer = (EntityReference)mainCustomerObj;
		Guid guid = mainCustomer.Id;
		string entityName = mainCustomer.LogicalName;
		string name = mainCustomer.Name;

		//Set value of Customer field and its attributes                        
		primaryEntity[mainCustomerLogicalName] = new EntityReference("account", new Guid("2E4D98F9-8EF9-E911-A2E8-005056AE4389"));
	}
}

Extra Details

The plugin demonstrated in this post was developed on Microsoft Dynamics 365 version 9.0.3.7 and Microsoft Dynamics 365 SDK version 9.0.2.12.