Reputation: 11
My config variables in docker-compose file can't read in Startup.cs. I'm using Asp.net Core 3.1 and SQL Server.
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)
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
}
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
Upvotes: 1
Views: 2161
Reputation: 35554
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")));
Upvotes: 3