Get Environment Variable in a Flow using Custom Web API

Inspired by a blog post by Natraj about “Using Custom API as a trigger for Flow” that you can find here, I am thinking to create a sample collection of Custom Web API that all people can make use of/learn the code (the code design might not be suitable for you, but I open for discussion for it of course). One of the initial ideas that I get is to call Environment Variable in the flow easily (original idea for this post without creating Custom API you can find it here).

Here is the flow design:

Flow to call environment variable

It’s so easy isn’t it to get the Environment Variable with the Custom Web API?

Before we jump into the code, let me explain a bit about Environment Variable.

Environment Variable

Environment Variable is a type of Solution Component that contains system configuration. It can be URL, numbers, JSON string, or anything else that basically will be used for the system process. With this approach, we don’t need to “hard-code” it and amend our process to get the correct value.

The design of the Environment Variable from what I see is like this:

The environment variable tables

Here is the sample Environment Variable that I created:

My sample of environment variable

For 1 of Environment Variable Definition, we can add only 1 Environment Variable Value. Even though the UI seems like we can add multiple Environment Variable Value, when you save the 2nd row, CRM will block it. This knowledge will be used for the logic of the code. And here is the Business Logic of the code:

using Insurgo.Custom.Entities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Niam.XRM.Framework;
using Niam.XRM.Framework.Data;
using Niam.XRM.Framework.Interfaces.Plugin;
using Niam.XRM.Framework.Plugin;
using System.Collections.Generic;
using System.Linq;

namespace Insurgo.Custom.Api.Business
{
    public class GetEnvironmentVariable : OperationBase<Entity>
    {
        public const string InputParameter = "EnvironmentVariableName";
        public const string OutputParameter = "Result";

        public class JsonValueModel
        {
            public string Name { get; set; }
            public string Value { get; set; }
        }

        public GetEnvironmentVariable(ITransactionContext<Entity> context) : base(context)
        {
        }

        protected override void HandleExecute()
        {
            var environmentVariableName =
                Context.PluginExecutionContext.InputParameters.ContainsKey(InputParameter)
                    ? Context.PluginExecutionContext.InputParameters[InputParameter].ToString()
                    : "";

            if (string.IsNullOrEmpty(environmentVariableName))
            {
                throw new InvalidPluginExecutionException($"{InputParameter} is empty!");
            }

            var data = GetData(environmentVariableName);
            var result = GetModel(data).Where(e => !string.IsNullOrEmpty(e.Value)).ToArray();
            var row = result.LastOrDefault() ?? new JsonValueModel();

            if (string.IsNullOrEmpty(row.Value))
            {
                throw new InvalidPluginExecutionException("Value is null!");
            }

            Context.PluginExecutionContext.OutputParameters[OutputParameter] = row.Value;
        }

        private IEnumerable<JsonValueModel> GetModel(EnvironmentVariableDefinition[] data)
        {
            if (data.Any())
            {
                var parent = data.FirstOrDefault();
                yield return new JsonValueModel
                {
                    Name = parent.Get(e => e.SchemaName),
                    Value = parent.Get(e => e.DefaultValue)
                };
            }

            foreach (var datum in data)
            {
                var child = datum.GetAliasedEntity<EnvironmentVariableValue>("ev");
                yield return new JsonValueModel
                {
                    Name = child.Get(e => e.SchemaName),
                    Value = child.Get(e => e.Value)
                };
            }
        }

        private EnvironmentVariableDefinition[] GetData(string environmentVariableName)
        {
            var query = new QueryExpression(EnvironmentVariableDefinition.EntityLogicalName)
            {
                ColumnSet = new ColumnSet<EnvironmentVariableDefinition>(e => e.DefaultValue, e => e.SchemaName)
            };
            query.Criteria.AddCondition<EnvironmentVariableDefinition>(e => e.SchemaName, ConditionOperator.Equal, environmentVariableName);

            var childLink =
                query.AddLink<EnvironmentVariableDefinition, EnvironmentVariableValue>(e => e.Id,
                    e => e.EnvironmentVariableDefinitionId, JoinOperator.LeftOuter);
            childLink.EntityAlias = "ev";
            childLink.Columns = new ColumnSet<EnvironmentVariableValue>(e => e.SchemaName, e => e.Value);

            var result = Service.RetrieveMultiple(query);

            var data = result.Entities.Any()
                ? result.Entities.Select(e => e.ToEntity<EnvironmentVariableDefinition>()).ToArray()
                : new EnvironmentVariableDefinition[] { };

            return data;
        }
    }
}

Scenario

  • If you only create Environment Variable Definition, then the code will direct return the EnvironmentVariableDefinition.DefaultValue.
  • If you create Environment Variable Definition and add Environment Variable Value, the code will return the EnvironmentVariableValue.Value.

Once all the code we done, we just need to register the plugin. Here is the screenshot of the Plugin:

Plugin registered

Create Web API Component

I will not explain in detail how I create the Custom Web API because you can check on Natraj’s post. But I just want to give you the flow chart to give you more understanding of the whole step by step of creating it:

Flow for creating Custom Web API + create a catalog

Here is the snapshot of my Custom Web API and yes, I’m using David Rivard‘s XrmToolBox Plugin:

Custom API Manager by David Rivard

I also tested the Custom Web API using Custom API Tester by Jonas Rapp. Here is the screenshot of my Custom Web API testing:

Custom API Tester by Jonas Rapp

The next steps were tedious, we needed to create 

Root Catalog > Create Child Catalog > Create Catalog Assignment. But once we do that, you can create the flow like in the first picture.

Here is the result I got when I successfully ran the Flow:

Success flow running

The code you can check on this Github Repository. Feel free to reach out to me + give ideas of what I need to create for the Custom API! Or you can collaborate with me on this sample project?

PS: In the repository, I include the Unit Testing also. So you can learn more about unit testing on the Dynamics CRM Plugin side!

Update

1) I’ve got a message from Carina that we actually can access the Environment Variable directly from the flow based on her screenshot:

Access environment variable directly from the flow

But the idea of this one is to create a collection set of Custom APIs that we can use in Javascript, or the Plugin as well. Also from this repository, I hope people can learn to implement unit testing in the Dynamics CRM world.

2) Based on Linn’s explanation, David also got his own version of Custom API that you can check here: https://github.com/drivardxrm/Dataverse-CustomApis/wiki/GetEnvironmentVariable

Related Links

Author: temmyraharjo

Microsoft Dynamics 365 Technical Consultant, KL Power Platform User Community Leader, Student Forever, Test Driven Development, and Human Code enthusiast.

2 thoughts on “Get Environment Variable in a Flow using Custom Web API”

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.