Windows Service with Azure Configuration Service

Joel Palmer (JLPM) 141 Reputation points
2021-09-10T15:02:34.457+00:00

I posted the program.cs code below in Exhibit 1 which creates the host. Note, that I ".UseWindowsService" and I "AddAzureAppConfiguration". The problem is that my build guy says that the install doesn't work if there is no internet access and this is unacceptable. Huh?

I believe I know the answer to this but thought I'd throw it out to the crowd. Is there a way to pull in the AzureAppConfiguration values after the service is up and running. That said, let me partially answer my question by showing Exhibit 2. This does seem to work but I don't know how to tie it back into the Default Builder once it grabs the values.

But then, to go back to the original question/requirement... will this allow the service to start and not fail on install when there is no internet access? Another way of asking is... can the service start up completely having only a base set of configuration values then be updated after it is running?

Exhibit 1:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.CaptureStartupErrors(true);
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
logging.AddNLog();
});
webBuilder.ConfigureKestrel(options =>
{
options.Listen(IPAddress.Loopback, 8080);
});
webBuilder.ConfigureAppConfiguration((context, config) =>
{
var builtConfig = config.Build();

                    config.AddAzureAppConfiguration(options =>
                    {
                        options.Connect(builtConfig[$"AppConfigEndpoint_{appSettings.Environment}"]
                            .Decrypt(EncryptionHelper.UniqueId))
                                .Select(KeyFilter.Any, "Deployed")
                                .Select(KeyFilter.Any, "Upload");
                    });
                });
            });

Exhibit 2:
string env = configuration.GetValue<string>($"CurrentEnvironment");
string endPoint = configuration.GetValue<string>($"AppConfigEndpoint_{env}");
IConfigurationBuilder configBuilder = new ConfigurationBuilder();
configBuilder.AddAzureAppConfiguration(options =>
{
options.Connect(endPoint);
options.Select(KeyFilter.Any, "Deployed")
.Select(KeyFilter.Any, "Upload");
});

        configuration = configBuilder.Build();
Azure App Configuration
Azure App Configuration
An Azure service that provides hosted, universal storage for Azure app configurations.
207 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,158 questions
Windows Server
Windows Server
A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.
12,121 questions
.NET Runtime
.NET Runtime
.NET: Microsoft Technologies based on the .NET software framework.Runtime: An environment required to run apps that aren't compiled to machine language.
1,119 questions
0 comments No comments
{count} votes

Accepted answer
  1. Joel Palmer (JLPM) 141 Reputation points
    2021-09-15T18:49:11.837+00:00

    I figured it out… all the pieces were there I just needed to glue them together.

    1. Create a new Project
    2. Define it as a Windows Service
    3. Do not define it to pull configuration values from Azure.
    4. Create a class (as shown) that will pull from Azure on demand
      a. Make it a singleton
      b. Start up with a timer.
      c. Once configuration values are captured delete the timer.
      d. Pass the singleton around everywhere that needs config values.
    5. Map values pulled from Azure to local properties.
      public bool Refresh()
      {
          bool result = false;
      
          try
          {
              string env = configuration.GetValue<string>($"CurrentEnvironment");
              string endPoint = configuration.GetValue<string>($"AppConfigEndpoint_{env}");
      
              IConfigurationBuilder configBuilder = new ConfigurationBuilder();
              configBuilder.AddAzureAppConfiguration(options =>
              {
                  options.Connect(endPoint.Decrypt())
                      .Select(KeyFilter.Any, "Deployed")
                      .Select(KeyFilter.Any, "Upload");
              });
      
              IConfiguration configs = configBuilder.Build();
      
              foreach (var item in configs.GetChildren())
              {
                  // map values to properties
      
                  Console.WriteLine($"{item.Key}: {item.Value}");
              }
      
              result = true;
          }
          catch (Exception ex)
          {
              Exception = ex;
          }
      
          return result;
      }
      
    1 person found this answer helpful.

3 additional answers

Sort by: Most helpful
  1. Joel Palmer (JLPM) 141 Reputation points
    2021-09-10T15:03:56.823+00:00

    Not sure why this post took some of my code and formatted it while it left the rest... nonetheless. Oop, there it is.

    0 comments No comments

  2. Bruce (SqlWork.com) 55,686 Reputation points
    2021-09-10T15:21:25.103+00:00

    it is common for servers to have internet access blocked. this means without firewall rules, your service can not access azure app setting. you could conditionally add the azure configuration based on a setting in the appsetting.json or a command line switch.


  3. Bruce (SqlWork.com) 55,686 Reputation points
    2021-09-10T19:53:20.397+00:00

    a command line switch is an alternative to local app setting. a command line provider is in the default config. see command line instructions. if you are running the service from the command line this will work. if using the services template, they all not work.

    to elevated privileges you need to start a new process with the runas option. you should give the service account the permission you need.

    0 comments No comments