Get and Set Dynamics 365 Environment Variables from JavaScript

Paul Nieuwelaar, 14 April 2022

Overview

Environments Variables are a useful feature of Dynamics 365 and the Power Platform. They allow us to use values in things like Power Automate which are environment specific, such as API details, which might be different in each environment.

image

When deploying environment variables to another environment you’ll be prompted to enter the value for that environment. Any logic, such as Power Automate Flow, will then automatically reference the environment specific value, rather than the default value.
Before environment variables were a thing, we would often create a ‘Settings’ entity with key/value pairs and use these to store environment specific information which could then be referenced by other logic.

That’s hopefully enough of an overview of Environment Variables. The Microsoft Docs go into more detail if needed.
If we want to access environment variables from code, e.g. JavaScript, we can simply query them like any other Dataverse table using the WebApi. Although, since the values can be stored in either the environment variable value, or the defaultvalue on the actual environment variable definition, there’s a little bit more to think about.

Get Environment Variable

The function below can be used to retrieve a specific value from an environment variable, which will first try to get the environment variable value specific to the current environment, or if it doesn’t exist, it simply returns the defaultvalue. If no environment variable definition with the specified schema name exists, it returns null.

  async function getEnvironmentVariable(schemaName) {
     var value = null;

    // Get the matching environment variable definition with related values
     var data = await Xrm.WebApi.retrieveMultipleRecords("environmentvariabledefinition", "?$top=1" +
         "&$select=environmentvariabledefinitionid,defaultvalue" +
         "&$expand=environmentvariabledefinition_environmentvariablevalue($select=value)" +
         `&$filter=schemaname eq '${schemaName}'`);

    if (data && data.entities && data.entities.length > 0) {
         // Definition exists
         var definition = data.entities[0];

        // Use the default value only if no related values
         value = definition.defaultvalue;

        // Get the related value if provided
         if (definition.environmentvariabledefinition_environmentvariablevalue.length > 0) {
             value = definition.environmentvariabledefinition_environmentvariablevalue[0].value;
         }
     }

    return value;
 }

This obviously requires that users have at least read access to both environment variable definitions and environment variable values. As it is an async function, it can be used with await or .then():

// Get value using await (async)
 let value = await getEnvironmentVariable("mag_variableschemaname");

// Or get value using .then()
getEnvironmentVariable("mag_variableschemaname").then(function (value) {

});


Set Environment Variable

If you want to update an environment variable value through JavaScript, it can be more difficult. If the definition doesn’t exist, this will create one. If the definition exists but a variable doesn’t, this will create the variable. Otherwise, if both the definition and variable exists, it will update the variable.

async function setEnvironmentVariable(schemaName, value, displayName) {
     // Make sure value is a string
     if (value !== null && typeof value !== "undefined") { value = value.toString(); }

    // Get the matching environment variable definition with related values
     var data = await Xrm.WebApi.retrieveMultipleRecords("environmentvariabledefinition", "?$top=1" +
         "&$select=environmentvariabledefinitionid" +
         "&$expand=environmentvariabledefinition_environmentvariablevalue($select=environmentvariablevalueid)" +
         `&$filter=schemaname eq '${schemaName}'`);

    if (data && data.entities && data.entities.length > 0) {
         // Definition exists
         var definition = data.entities[0];
         var definitionId = definition.environmentvariabledefinitionid;

        if (definition.environmentvariabledefinition_environmentvariablevalue.length > 0) {
             // Related value exists - Update value
             var valueId = definition.environmentvariabledefinition_environmentvariablevalue[0].environmentvariablevalueid;
             await Xrm.WebApi.updateRecord("environmentvariablevalue", valueId, { "value": value });
         }
         else {
             // Related value doesn't exist - Create value
             var attributes = {
                 "value": value,
                 "EnvironmentVariableDefinitionId@odata.bind": `/environmentvariabledefinitions(${definitionId})`
             };

            await Xrm.WebApi.createRecord("environmentvariablevalue", attributes);
         }
     }
     else {
         // Definition doesn't exist - Deep create both definition and value
         var attributes = {
             "schemaname": schemaName,
             "displayname": displayName || key,
             "environmentvariabledefinition_environmentvariablevalue": [
                 {
                     "value": value
                 }
             ]
         };

        await Xrm.WebApi.createRecord("environmentvariabledefinition", attributes);
     }
 }

This requires that users have read, create, and update permissions on environment variables and definitions, so you may want to consider whether this is OK for the wider system. This function is also async, but because it doesn’t return any value, it’s OK to just call it normally, unless you specifically need to wait for it to update:

// Set value, and await a response (async)
await setEnvironmentVariable("mag_variableschemaname", "new-value");

// Set value and wait for response using .then()
setEnvironmentVariable("mag_variableschemaname", "new-value").then(function () {

});

// Set value without waiting
setEnvironmentVariable("mag_variableschemaname", "new-value");

You can also optionally provide a 3rd parameter as the environment variable definition display name, which is used if/when it creates a new definition. Otherwise if this is left blank, the display name will be set to the same as the schemaName.