1

I am using Azure KeyVault to get secrets in Program.cs:

public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, config) =>
                {
                    config.SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("appsettings.json", optional: false)
                        .AddEnvironmentVariables();

                    var builtConfig = config.Build();

                    config.AddAzureKeyVault(
                        $"https://{builtConfig["KeyVault:Name"]}.vault.azure.net/",
                        builtConfig["KeyVault:ClientId"],
                        builtConfig["KeyVault:ClientSecret"]);
                })
                .UseStartup<Startup>()
                .UseApplicationInsights()
                .Build();

I have following code to seed data in Startup.cs inside of ConfigureServices so I could get Azure KeyVault values:

    Task.Run(async () =>
    {
            try
            {
                var context = services.BuildServiceProvider().GetRequiredService<ApplicationDbContext>();
                var userManager = services.BuildServiceProvider().GetRequiredService<UserManager<ApplicationUser>>();

                await SeedData.Initialize(context, userManager, Configuration);
            }
            catch (Exception ex)
            {
                var logger = services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred seeding the DB.");
            }
    });

Method:

public class SeedData
    {
        public static async Task Initialize(ApplicationDbContext context, UserManager<ApplicationUser> userManager, IConfiguration configuration)
        {
            // Look for any users.
            if (context.Users.Any())
            {
                return; // DB has been seeded
            }

            var user = new ApplicationUser
            {
                Email = configuration["SeedData:InitialAdminUser"],
                UserName = configuration["SeedData:InitialAdminUser"]
            };

            var password = configuration["SeedData:InitialAdminPassword"];
            await userManager.CreateAsync(user, password);
            await userManager.AddClaimAsync(user, new Claim(ClaimTypes.Role, "admin"));
        }
    }

To seed data it is recommended to use it in Program.cs instead of Startup. Why is that?

I had this in Program.cs but I couldn't get config values from AzureKeyVault, because AzureKeyVault is configured after(I can't get azure key vault secret values at this stage):

public class Program
    {
        public static void Main(string[] args)
        {
            var host = BuildWebHost(args);

            Task.Run(async () =>
            {
                // seeding initial admin user
                using (var scope = host.Services.CreateScope())
                {
                    var services = scope.ServiceProvider;
                    try
                    {
                        var context = services.GetRequiredService<ApplicationDbContext>();
                        var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();

                        var builder = services.GetRequiredService<IConfigurationRoot>();

                        await SeedData.Initialize(context, userManager, builder);
                    }
                    catch (Exception ex)
                    {
                        var logger = services.GetRequiredService<ILogger<Program>>();
                        logger.LogError(ex, "An error occurred seeding the DB.");
                    }
                }
            });

            host.Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, config) =>
                {
                    config.SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("appsettings.json", optional: false)
                        .AddEnvironmentVariables();

                    var builtConfig = config.Build();

                    config.AddAzureKeyVault(
                        $"https://{builtConfig["KeyVault:Name"]}.vault.azure.net/",
                        builtConfig["KeyVault:ClientId"],
                        builtConfig["KeyVault:ClientSecret"]);
                })
                .UseStartup<Startup>()
                .UseApplicationInsights()
                .Build();
    }

To achieve this in Program.cs I think one way is to move azurekeyvault to main before Task.Run?

What reckon you?

sensei
  • 7,044
  • 10
  • 57
  • 125
  • What do you mean you can't get it? The code `ConfigureAppConfiguration` previously happened in the startup constructor and `ConfigureServices` happens before you run the host (how else would you create a scope and resolve your DbContext). See my answer [here](https://stackoverflow.com/a/45942026/455493) as for the **WHY** in `Program` class – Tseng May 20 '18 at 15:39
  • makes sense ill have a look – sensei May 20 '18 at 16:39

0 Answers0