Home > Software design >  ASP.Net Core Web Api - Use production and test database connection strings
ASP.Net Core Web Api - Use production and test database connection strings

Time:08-05

I am building a web api with asp.net core and I wanted to ask how you would handle production and test environments inside the api. The goal would be to publish the web api on the IIS and then for it to use the production db connection string. When I start my api locally I would like my api to connect to the test database without me changing a lot of stuff in the code.

In my Startup.cs I use Entity Framework like this:

services.AddDbContextFactory<ProdContext>(options =>
{
    string decrypted = ConnStringSecurity.Decrypt(Configuration.GetConnectionString("ProdDBConnection"));

    options.UseSqlServer(decrypted,
    sqlServerOptionsAction: sqlOptions =>
    {
        sqlOptions.EnableRetryOnFailure(
        maxRetryCount: 10,
        maxRetryDelay: TimeSpan.FromSeconds(5),
        errorNumbersToAdd: null
        );
    });
});

services.AddDbContextFactory<TestContext>(options =>
{
    string decrypted = ConnStringSecurity.Decrypt(Configuration.GetConnectionString("TestDBConnection"));

    options.UseSqlServer(decrypted,
    sqlServerOptionsAction: sqlOptions =>
    {
        sqlOptions.EnableRetryOnFailure(
        maxRetryCount: 10,
        maxRetryDelay: TimeSpan.FromSeconds(5),
        errorNumbersToAdd: null
        );
    });
});

In the Configure method I see that you can differentiate between development and production but I can't quite imagine how the DbContexts can be integrated in the if statement:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
    if (env.IsDevelopment())
    {
        //Use Test Db globally
        app.UseDeveloperExceptionPage();
    }
    else if(env.IsProduction())
    {
       //Use Prod Db globally
    }


}

Also in every Controller I inject the Context that I need so to make this happen I would have to check on every endpoint if I am currently in development or production. Is there a more efficient way to do this? The 'lazy' approach would be to publish two instances of my api, one for prod and one for test where the code is changed accordingly.

CodePudding user response:

You can inject IWebHostEnvironment to the Startup class by its constructor, which is the same one as you have among the parameters of Startup.Configure method. Then, you can use env.IsDevelopment() in the Startup.ConfigureServices method, where you set up DB context.

I wonder if you really want to different DB contexts in the development and production environment.

So, having a single context MyDbContext for both environments, Startup class becomes like below. Then, your controllers will get MyDbContext instance injected which connects to a different DB by the environment.

    public class Startup
    {
        public IConfiguration Configuration { get; }
        private readonly IWebHostEnvironment _env;

        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            Configuration = configuration;
            _env = env;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MyDbContext>(options =>
            {
                string decrypted = ConnStringSecurity.Decrypt(Configuration.GetConnectionString(
                    _env.IsDevelopment() ?  "TestDBConnection" : "ProdDBConnection"));
                options.UseSqlServer(decrypted,
                    sqlOptions =>
                    {
                        sqlOptions.EnableRetryOnFailure(
                            maxRetryCount: 10,
                            maxRetryDelay: TimeSpan.FromSeconds(5),
                            errorNumbersToAdd: null
                            );
                    });
            });

CodePudding user response:

The Microsoft docs article secrets.json

you can add all your sensitive key value pairs on the secrets.json when developing. the same keys in the appsetting.json will be overridden by secrets.json if they have the same key.

for production you can create application level variables by the same key value pair or use key-vault, or use app configuration if you are hosting in azure web app service.

  • Related