1

My config variables in docker-compose file can't read in Startup.cs. I'm using Asp.net Core 3.1 and SQL Server.

This is my error message

blog-app_1      | warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
blog-app_1      |       Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
blog-app_1      | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
blog-app_1      |       No XML encryptor configured. Key {58394e97-3215-43de-abbc-ae7ab801d661} may be persisted to storage in unencrypted form.
blog-app_1      | crit: Microsoft.AspNetCore.Hosting.Diagnostics[6]
blog-app_1      |       Application startup exception
blog-app_1      | System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
blog-app_1      |    at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName)
blog-app_1      |    at Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 sqlServerOptionsAction)
blog-app_1      |    at BlogApplication.Startup.<>c__DisplayClass4_0.<ConfigureServices>b__1(DbContextOptionsBuilder options) in /src/BlogApplication/Startup.cs:line 56
blog-app_1      |    at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass1_0`2.<AddDbContext>b__0(IServiceProvider p, DbContextOptionsBuilder b)
blog-app_1      |    at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions[TContext](IServiceProvider applicationServiceProvider, Action`2 optionsAction)

This is my Startup.cs

I'm using Configuration["..."] to initial environment variables. You can see it in public void ConfigureServices(IServiceCollection services).

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();

        services.AddControllersWithViews().AddJsonOptions(option =>
        {
            option.JsonSerializerOptions.PropertyNamingPolicy = null;
            option.JsonSerializerOptions.DictionaryKeyPolicy = null;
        });

        //Config Database Identity
        var server_identity = Configuration["DBServer"] ?? "mssql-server";
        var port_identity = Configuration["DBPort"] ?? "1433";
        var user_identity = Configuration["DBUsername"] ?? "sa";
        var password_identity = Configuration["DBPass"] ?? "Loc@04071999";
        var dbName_identity = Configuration["DBNameIdentity"] ?? "Identity_BlogApplication";

        //Config Database Blog
        var dbName_blog = Configuration["DBNameBlog"] ?? "Data_BlogApplication";

        string DefaultConnection = $"Server={server_identity}, {port_identity}; Database={dbName_identity}; User ID={user_identity}; Password={password_identity}";
        string DataConnection = $"Server={server_identity}, {port_identity}; Database={dbName_blog}; User ID={user_identity}; Password={password_identity}";

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString(DefaultConnection)));
        services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddDbContext<BlogApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString(DataConnection)));

        services.AddTransient<ICommentService, CommentService>();
        services.AddTransient<IBlogService, BlogService>();

        services.AddControllersWithViews().AddRazorRuntimeCompilation();
        services.AddRazorPages();

        //services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Blog}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });

        
        app.ApplicationServices.CreateScope().ServiceProvider.GetService<ApplicationDbContext>().Database.Migrate();
        app.ApplicationServices.CreateScope().ServiceProvider.GetService<BlogApplicationDbContext>().Database.Migrate();
    }c
}

This is my docker-compose.xml

and in docker-compose, I set "environment: " for blog-app

version: '3'
services:
  mssql-server:
    image: "microsoft/mssql-server-linux"
    environment:
      ACCEPT_EULA: "Y"
      SA_PASSWORD: "Loc@04071999"
      MSSQL_PID: Express
    ports:
      - "1433:1433"
  blog-app:
    build: .
    environment:
      DBServer: "mssql-server"
      DBPort: "1433"
      DBUsername: "sa"
      DBPass: "Loc@04071999"
      DBNameIdentity: "Identity_BlogApplication"
      DBNameBlog: "Data_BlogApplication"
    ports: 
      - "3000:80"

Thanks for see my problem

1 Answer 1

3

The method Configuration.GetConnectionString() you use gets the connection-string with the provided name from the configuration. In your case the name is the value of variable DefaultConnection. The variable should have value

$"Server=mssql-server, 1433; Database=Identity_BlogApplication; User ID=sa; Password=Loc@04071999"; 

But a connection string with this name does not exist and therefore null is returned and you get the ArgumentNullException.

You may fix it by not calling Configuration.GetConnectionString() and instead pass your connection-strings directly to method UseSqlServer, because you build the connection-string by yourself with the values of your environment variables.

So the following should fix your problem.

services.AddDbContext<ApplicationDbContext>(options =>  options.UseSqlServer(DefaultConnection));
...
services.AddDbContext<BlogApplicationDbContext>(options => options.UseSqlServer(DataConnection));

But IMHO you should not build the connection-string by yourself, but provide the full connection-string to your database with a single environment variable. This is done using a connecting-string environment variable (CONNECTIONSTRINGS)

version: '3'
services:
  mssql-server:
    image: "microsoft/mssql-server-linux"
    environment:
      ACCEPT_EULA: "Y"
      SA_PASSWORD: "Loc@04071999"
      MSSQL_PID: Express
    ports:
      - "1433:1433"
  blog-app:
    build: .
    environment:
      CONNECTIONSTRINGS__IDENTITY: "Server=mssql-server, 1433; Database=Identity_BlogApplication; User ID=sa; Password=Loc@04071999"
      CONNECTIONSTRINGS__BLOG: "Server=mssql-server, 1433; Database=Data_BlogApplication; User ID=sa; Password=Loc@04071999"
    ports: 
      - "3000:80"

Using this approach you can use the call Configuration.GetConnectionString() in your code like

services.AddDbContext<ApplicationDbContext>(options =>  options.UseSqlServer(Configuration.GetConnectionString("IDENTITY")));
...
services.AddDbContext<BlogApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("BLOG")));
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your help. I follow your fix, but I have a new problem
THIS IS MY NEW PROBLEM: blog-app_1 | crit: Microsoft.AspNetCore.Hosting.Diagnostics[6] blog-app_1 | Application startup exception blog-app_1 | Microsoft.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 40 - Could not open a connection to SQL Server)
I have been solve my problem. In docker-compose file change this line: image: "microsoft/mssql-server-linux --change-> image: "mcr.microsoft.com/mssql/server:2019-latest"
Thank you so much. Close my topic !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.