Page 12 - MSDN Magazine, May 2019
P. 12

solutions have existed for quite some time. With respect to securing the secrets, the new secrets management tool in ASP.NET Core can help during development. See the documentation at bit.ly/2HeVgVr for details.In addition, the appsettings.json file is text and anyone can read it from your source control if you accidentally push it to a public repository along with an app.
A better path for the containerized solution is to use Docker environment variables, which the app can read at run time while continuing to be able to run migration commands at design time. This also gives you the flexibility to provide values to those variables dynamically.
For running and debugging locally in Docker, I can switch to a SQL Server on my network or point to the Azure SQL Database.
Here’s the plan: I’ll use SQL Server LocalDB at design time, as well as for testing out the app “on metal”; that is, when debugging against the Kestrel or IIS servers. And because LocalDB doesn’t need credentials, I don’t have to worry about secrets in its connection string. For running and debugging locally in Docker, I can switch to a SQL Server on my network or point to the Azure SQL Database. Finally, for the production version of the containerized app, I’ll be sure it’s pointing to the Azure SQL Database. Throughout, you’ll see how you can use Windows and Docker environment variables to keep your secrets secret.
And here’s something that’s a great convenience: Because all of these approaches use some flavor of SQL Server, I can always use the same provider, Microsoft.EntityFrameworkCore.SqlServer.
Moving the Development Connection String
design time and the environment variable provided by Docker- file at run time, I need to employ a different syntax for the UseSqlServer options. Currently (and most commonly), you use Configuration.GetConnectionString to read the string from app- settings files. That won’t work, however, for environment variables, whether they’re from Windows or Docker. GetConnectionString is a helper method that supplants referencing the property name directly.
But I can read both the appsettings values and any environment values as key-value pairs using this syntax:
services.AddDbContext<MagContext>(options => options.UseSqlServer(
Configuration["ConnectionStrings:MagsConnectionMssql"]));
Let’s verify that EF Core migrations can find the connection string in appsettings.Development.json, which you can do by running the PowerShell migration command Get-DbContext. This forces EF Core to do the same work as with any of the other migration commands, and results in output that shows the provider name, database name and data source:
providerName databaseName dataSource options ------------ ------------ ---------- ------- Microsoft.EntityFrameworkCore.SqlServer DP0419Mags (localdb)\mssqllocaldb None
Creating a Connection String for Docker’s Eyes Only
So now I know appsettings works at design time. What about letting Docker find its alternate connection string when the con- tainer is running, without having to modify startup.cs as you go back and forth?
It’s helpful to know that the CreateWebHostBuilder method called in program.cs calls AddEnvironmentVariables, which will read available environment variables and store them as key-value pairs in Configuration data.
Docker has a command called ENV that lets you set a key-value pair. I’ll begin by hardcoding this into the Dockerfile. I can set a new key with the same name as the one in the JSON file, which is what the UseSqlServer configuration is expecting. I can even include the colon in the key’s name. I put my ENV variables in the file before the build image is created. Figure 2 shows the Dockerfile, including the new ENV variable. I described the contents of this file in Part 1 of this series, in case you need to go back for a refresher. Note that
to Development Settings
ASP.NET Core will default to the appsettings.Development.json set- tings file when running from Visual Studio, but in production it defaults to appsettings.json.
I’ll remove the entire connection- Strings section from appsettings.json and, instead, add the LocalDB con- nection string into appsettings.Devel- opment.json. You’ll find this file if you expand the arrow glyph next to appset- tings.json in Solution Explorer:
"ConnectionStrings": { "MagsConnectionMssql":
"Server=(localdb)\\mssqllocaldb;Database= DP0419Mags;Trusted_Connection=True;"
Because I want the app to be able to read both this connection string at
I’ve abbreviated the connection string here for readability.
Let’s see what impact this has. Be sure the debug profile is pointed to Docker and let’s actually debug this time. I’ll set a breakpoint just after the AddDbContext command in Startup.cs and debug, and then inspect the value of Configuration["Connection- Strings:MagsConnectionMssql"]. I can see that it now returns the Azure SQL Database connection string, not the LocalDb connection string. Debugging into all of the available configuration data, I can see that the appsettings con- nection string is also loaded into the Configuration object. But as explained by Randy Patterson in his blog post at
}
8 msdn magazine
Data Points
Figure 1 The API's Output, Listing Three Magazines Defined Using Seeding in the DbContext


































































































   10   11   12   13   14