0

I've created an Azure Function that retrieves new form inputs from a website, processes them and stores the result in another system by using an API call. I only want to retrieve the form inputs that have not been processed before. This is supported by the website. I'm reading the timestamp of the most recent form input that has already been processed. This works fine.

I'm using the following function to read the setting from the Azure function environment:

private static string GetEnvironmentVariable(string name)
{
    return System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
}

After I've processed a form input, I store the timestamp of the form with the following function:

private static void SetEnvironmentVariable(string name, string value)
{
    System.Environment.SetEnvironmentVariable(name, value, EnvironmentVariableTarget.Process);
}

Everything seems to be working fine. I see in the logs that form inputs don't get processed more than once. However, when I take a look at the environment variables in the Azure dashboard, I can see that the initial value of the variable is still present. This initial value will be used when the environment 'shuts down' and is restarted (e.g. after changing the value of another environment variable).

I've tried to change the target from 'Process' to 'Machine', but this results in access control errors. There are some questions on SO that are related to my issue, but none of them provides me with an answer for my situation.

I would like to know whether:

  1. Environment variables are the / a suited solution for my use case;
  2. If so, how can I prevent that a variable will be reset to its initial value after resetting the Azure environment.

Thanks in advance!

Björn Boxstart
  • 1,098
  • 1
  • 12
  • 25
  • 1
    I would suggest **NOT** to save the transaction data into Environment variables as those are not persisted across instances. A new Azure function can be spin up any time based on the load on a new machine (VM) and which would not have access to a variable which are set on another machine. I would suggest go for a persistent storage like `Azure table` which is cheap and would be well suited for your need. – user1672994 Jan 25 '21 at 04:02
  • @user1672994 I will take a look into this. I expect that this can be a solution for my problem. It seems to me that this will also mean that my local development will be coupled to Azure table storage. My current solution can be tested locally without a connection with Azure. – Björn Boxstart Jan 25 '21 at 09:48
  • 1
    you can use the local azure storage emulator for local development. – user1672994 Jan 25 '21 at 09:52
  • @user1672994 thanks for the tip. I wasn't aware of that, but it looks promising! – Björn Boxstart Jan 25 '21 at 09:59

1 Answers1

2

Firstly, the Environment.SetEnvironmentVariable method already worked in your case.

Here is an answer from Hury Shen:

When you set the variable by Environment.SetEnvironmentVariable, it will not show in application setting. But we can use it by Environment.GetEnvironmentVariable as expected. Although the solution you mentioned is not so good, but it can implement your requirement. The adverse effect is when you restart the function app, the variables will be lost.

About the target Machine: The environment variable is stored or retrieved from the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment key in the Windows operating system registry. This value should be used on .NET implementations running on Windows systems only.


One way to achieve but not set inside code:

In App Service, you can set app settings outside of your app code. Then you can access them in any class using the standard ASP.NET Core dependency injection pattern:

using Microsoft.Extensions.Configuration;

namespace SomeNamespace 
{
    public class SomeClass
    {
        private IConfiguration _configuration;
    
        public SomeClass(IConfiguration configuration)
        {
            _configuration = configuration;
        }
    
        public SomeMethod()
        {
            // retrieve nested App Service app setting
            var myHierarchicalConfig = _configuration["My:Hierarchical:Config:Data"];
            // retrieve App Service connection string
            var myConnString = _configuration.GetConnectionString("MyDbConnection");
        }
    }
}
Doris Lv
  • 3,083
  • 1
  • 5
  • 14
  • It seems to me that your solution is more or less the same as what I'm currently using. I'm using the 'app settings outside of my code' (see my question). I've also mentioned that everyting is working fine, but that my challenge is that after a restart of the function app these values also are being reset. – Björn Boxstart Jan 25 '21 at 09:43
  • Do you mean the value in **app settings** had been reset? – Doris Lv Jan 25 '21 at 09:45
  • Actually, during execution of the function it only is updated in memory (at least that's my conclusion), because in the Azure portal, the value remains the same as how I manually have entered it, but in the logs of my function I can see that a new value is used on subsequent calls. – Björn Boxstart Jan 25 '21 at 09:56