IConfiguration returning null. Cannot Read from Database - c#

I have a .Net Core 3.1 Program returning the error
System.ArgumentNullException: 'Value cannot be null. (Parameter 'connectionString')'
when I try to login to the system.
I have set a breakpoint onto
public IConfiguration Configuration { get; }
On building,the connection string can be seen but immediately I login it returns null.
Below is my code.
Startup.cs
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddSession();
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/Login/Login", "");
});
services.AddDbContext<CENTREContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DatabaseConnection")));
//var connection = Configuration.GetConnectionString("ConnectionStrings");
//services.Configure<ConnectionStrings>(Configuration.GetSection("DatabaseConnection"));
//services.AddDbContext<CENTREContext>(options => options.UseSqlServer(connection));
}
ContextClass
public CENTREContext(DbContextOptions<CENTREContext> options)
: base(options)
{
}
public CENTREContext()
{ }
public IConfiguration Configuration { get; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(Configuration.
GetConnectionString("ConnectionStrings:DatabaseConnection"));
}
}
appsettings.json
{
"ConnectionStrings": {
"DatabaseConnection": "Server=xx-xx;Database=CENTRE;UID=xx;Password=xxx;"
},
"AllowedHosts": "*"
}
I have tried but nothing seems to work.
Help on the same will be appreciated.

You have mixed your options.
GetSection + index operator
connectionStrings = configuration.GetSection("ConnectionStrings");
connectionString = connectionStrings["DatabaseConnection"];
GetSection + path
connectionString = configuration.GetSection("ConnectionStrings:DatabaseConnection").Value;
GetConnectionString
connectionString = configuration.GetConnectionString("DatabaseConnection");

Related

Error CS1503 - Cannot convert from Microsoft.Extensions.Configuration.IConfigurationSection to System.Action<>

I am getting an error:
Error CS1503 Argument 2: cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationSection' to 'System.Action<>
When I am using Configure with Bind(), it is working.
var bandConfig = new BandSettings();
Configuration.GetSection("BandSettings").Bind(bandConfig );
But with the below code, I am getting the above error.
I tried many solutions suggested in blogs and other forums,
For example - Getting value from appsettings.json in .net core
but still the same error. Am I missing anything??
I have below things in place:
appsettings.json
"BandSettings":{
"UserID": "aTestUserID",
"Password" : "aTestPassword"
}
BandSettings.cs
public class BandWidthSettings
{
public string UserID { get; set; }
public string ApiToken { get; set; }
}
TestHelper.cs
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public static IConfiguration GetTestConfiguration()
=> new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
public IConfiguration Configuration { get; }
public TestHelper(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
var config = new BandSettings();
var bandSettingsSection = Configuration.GetSection("BandSettings");
services.Configure<BandSettings>(bandSettingsSection); //Error is getting on this line - bandSettingsSection
}
Add NuGet package Microsoft.Extensions.Options.ConfigurationExtensions to get the extension method where
services.Configure<BandSettings>(Configuration.GetSection("BandSettings"));
will work.
Reference: https://github.com/dotnet/AspNetCore.Docs/issues/18833
Create a POCO for the setting
public class MySetting
{
public string Setting{ get; set; }
}
On Startup it works perfectly as it should be:
services.Configure<MySetting>(Configuration.GetSection("MySetting"));
However on my the dependecy injection add the bind as mentioned in the question comments.
private static void ConfigureServices(IServiceCollection services)
{
var mySection = configuration.GetSection("MySetting");
services.Configure<MySetting>(c => mySection .Bind(c));
}
public IConfiguration Configuration { get; }
public TestHelper(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
//Configure section binding
services.Configure<BandSettings>(Configuration.GetSection(BandSettings.SECTION));
}

Read appsettings.json - Fields remain null

Think I have a problem with the startup.cs as I do not get any values from my <IOption> config
So.. We have our appsettings.json
"Config": {
"ApplicationName": "some name",
"ConnectionString": "someconstring",
"Version": "1.0.0"
},
Here we have our model
public class Config
{
public string ApplicationName { get; set; }
public string ConnectionString { get; set; }
public string Version { get; set; }
}
The startup.cs
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public static IConfiguration Configuration { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// Add functionality to inject IOptions<T>
services.AddOptions();
// Add our Config object so it can be injected
services.Configure<Config>(Configuration);
}
And then in our controller I try to load those data but unfortunately they remain empty.
private IOptions<Config> config;
public CompaniesController(IOptions<Config> config)
{
this.config = config;
}
I've tried to change the startup.cs with something like
services.Configure<Config>(options =>
{
options.ConnectionString = Configuration.GetSection("Config:ConnectionString").Value;
});
but that doesn't seems to work.
Resources I've been using:
https://dzone.com/articles/dynamic-connection-string-in-net-core
https://stackoverflow.com/questions/31453495/how-to-read-appsettings-values-from-json-file-in-asp-net-core
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.2
but Obviously I am missing a crucial point here.
edit: I am using ASP.Net Core 2.0
edit2:
the Program.cs
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
The entire Appsettings.json file
{
"Config": {
"ApplicationName": "somename",
"ConnectionString": "someconstring",
"Version": "1.0.0"
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
edit 3:
In my front-end application I import the API like this.
services.Configure<Config>(Configuration);
This line doesn't achieve the desired result because the JSON properties you're looking for are nested under a Config property in your appsettings.json file. To load these values as intended, use GetSection to grab the Config section and pass that into the Configure<TOptions> method:
services.Configure<Config>(Configuration.GetSection("Config"));
services.Configure<Config>(options =>
{
options.ConnectionString = Configuration.GetValue<string>("Config:ConnectionString");
options.ApplicationName = "test";
});
If you want to configure your options more granuarly.

Issues reading appsettings.json file C# .NET Core

I'm coming from regular .NET Web API and I have found the experience around configuration in .NET Core 2 absolutely maddening.
I have read the official documentation and a few tutorials such as this one, but they all see to error.
I have a Database helper class that is supposed to establish a MongoDB connection.
My configuration is rather simple
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "mongodb://localhost:27017"
}
}
I started with the .NET Core official Angular (ngx) boilerplate template
I add the configuration as a service singleton in Startup.CS under the ConfigureServices section like so services.AddSingleton(Configuration);
I attempt to inject the configuration into my class like so
public class DatabaseHelper
{
public static string connstring { get; private set; }
public DatabaseHelper(IConfiguration Configuration)
{
connstring = Configuration["ConnectionStrings:DefaultConnectionString"];
}
public static IMongoDatabase QuizDB { get; } = GetDatabase("QuizEngine");
public static IMongoCollection<Quiz> QuizCol { get; } = GetQuizCollection();
public static MongoClient GetConnection() {
return new MongoClient(connstring);
}
public static IMongoDatabase GetDatabase(string database) {
MongoClient conn = DatabaseHelper.GetConnection();
return conn.GetDatabase(database);
}
public static IMongoCollection<Quiz> GetQuizCollection() {
return DatabaseHelper.QuizDB.GetCollection<Quiz>("Quizzes");
}
}
This compiles and builds fine with no Intellesense errors - But when I step through it in the debugger, the connstring is null. I have tried playing around with the configuration names etc, but I always seem to come up empty.
I have also tried the POCO way using the example code in the below answer, but I seem to run into static field initializer issues.
Getting value from appsettings.json in .net core
if it helps here is the the startup class part where it sets the public value of Configuration
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
You don't need to add the configuration as a service singleton in Startup.CS under the ConfigureServices section like services.AddSingleton(Configuration);
If you separate your solution into multiple projects with use of class libraries, Microsoft.Extensions.Options.ConfigurationExtensions package comes in handy for reading the values from appsettings files and injecting them into your configuration classes within projects.
It has 2 extensions you can use:
public static T Get<T>(this IConfiguration configuration);
public static IServiceCollection Configure<TOptions>(this IServiceCollection services,
IConfiguration config) where TOptions : class;
your configuration file appsetting.json
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MongoDBConnection": "mongodb://localhost:27017"
}
}
add code for ConfigureServices method in startup.cs file
services.Configure<MongoDBconfig>(Configuration.GetSection("ConnectionStrings"));
services.AddSingleton<DatabaseHelper>();
your DBhelper.cs
public class MongoDBconfig
{
public string MongoDBConnection { get; set; }
}
public class DatabaseHelper
{
public static string connstring { get; private set; }
public DatabaseHelper(IOptions<MongoDBconfig> Configuration)
{
connstring = Configuration.Value.MongoDBConnection;
}
public static IMongoDatabase QuizDB { get; } = GetDatabase("QuizEngine");
public static IMongoCollection<Quiz> QuizCol { get; } = GetQuizCollection();
public static MongoClient GetConnection()
{
return new MongoClient(connstring);
}
public static IMongoDatabase GetDatabase(string database)
{
MongoClient conn = DatabaseHelper.GetConnection();
return conn.GetDatabase(database);
}
public static IMongoCollection<Quiz> GetQuizCollection()
{
return DatabaseHelper.QuizDB.GetCollection<Quiz>("Quizzes");
}
}
Try the following way using this extension method GetConnectionString
public DatabaseHelper(IConfiguration Configuration)
{
connstring = Configuration.GetConnectionString("DefaultConnection");
}
Try this
public DatabaseHelper(IConfiguration Configuration)
{
string test = Configuration.GetSection("ConnectionStrings")["DefaultConnection"];
Console.WriteLine(test);
}
Check if this able to extract the value in your appsettings.json

How to read appsettings.json in context in another project? Asp.Net Core

I need to use the same ConnectionString in two places. In my web project Insig.Api which contains ConnectionString from appsettings.json and in another project class library Insing.Infrastructure where is my db context.
Insig.Api - Startup.cs
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton(Configuration);
services.AddDbContext<InsigContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
}
Insig.Infrastructure - InsigContext.cs
public class InsigContext : DbContext, IDesignTimeDbContextFactory<InsigContext>
{
public InsigContext() { }
public InsigContext(DbContextOptions<InsigContext> options) : base(options) { }
public DbSet<Sample> Samples { get; set; }
public InsigContext CreateDbContext(string[] args)
{
var builder = new DbContextOptionsBuilder<InsigContext>();
builder.UseSqlServer("Data Source=.\\SQLEXPRESS;Initial Catalog=InsigDB;Integrated Security=True;MultipleActiveResultSets=True");
// Here I would like to use ConnectionString instead of raw string.
return new InsigContext(builder.Options);
}
}
As you can see ConnectionString is needed in context as well because of Migrations (from Code First approach).
EDIT - code below doesn't work. When I'm trying to Add-Migration Init then I receives an error: Value cannot be null. Parameter name: connectionString
public class InsigContext : DbContext
{
private readonly string _connectionString;
public InsigContext(DbContextOptions<InsigContext> options, IConfiguration configuration) : base(options)
{
_connectionString = configuration.GetSection("ConnectionStrings:DefaultConnection").Value;
}
public InsigContext() { }
public DbSet<Sample> Samples { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
}
You can inject IConfiguration to your InsigContext constructor and use that to get the connection string
private readonly string connectionString;
public InsigContext(DbContextOptions<InsigContext> options,IConfiguration configuration)
: base(options)
{
this.connectionString = configuration.GetSection("ConnectionStrings:DefaultConnection")
.Value;
}
// you can use this.connectionString now
IConfiguration is defined in Microsoft.Extensions.Configuration namespace. So you probably want to add a reference to that in your class libarary.
If you want access to the IConfiguration object in another method, create a local variable and set that in your constructor
private readonly IConfiguration configuration;
public InsigContext(IConfiguration configuration)
{
this.configuration = configuration;
}
public void CreateDbContext(string[] args)
{
// you can use this.configuration here as needed or get conn string
}
No need of multiple constructors. Keep one constructor where you are injecting the dependencies you want.
I decided to provide additional information for my comment.
Like the author, I faced the same issue to pass connection string to Data project from API project. I decided to specify global settings with connection string and linked them to both projects. I went step by step through this article. In result I've managed to use connection string in two places.
1) First create a folder name "Settings" in your data access layer project and create static AppSettings class inside that folder with a static string property name "ConnectionString" like below:
public static class AppSettings
{
public static string ConnectionString { get; set; }
}
2) Then add connectionstring to your appsettings.json file:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"ConString": "Data Source=serverName;Initial Catalog=DB_Name;uid=sa;pwd=12345;"
}
}
3) Add the statement below into your Startup() method in Startup.cs class in your UI layer to get the connection string:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
AppSettings.ConnectionString = Configuration.GetSection("ConnectionStrings")["ConString"];
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<YourDbContext>(option => {
option.UseSqlServer(AppSettings.ConnectionString);
});
}
}
That's all! Now whenever you want to use your connectionstring just call AppSettings.ConnectionString and it will help you.
You should inject the IConfiguration interface in your other project using dependency injection. Like this:
private readonly IConfiguration _config;
public InsigContext(IConfiguration config) {
_config = config;
}
Then u can use the _config.GetConnectionString("DefaultConnection");method to get the connection string.

How to read connection string in .NET Core?

I want to read just a connection string from a configuration file and for this add a file with the name "appsettings.json" to my project and add this content on it:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-
WebApplica71d622;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
On ASP.NET I used this:
var temp=ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
Now how can I read "DefaultConnection" in C# and store it on a string variable in .NET Core?
The posted answer is fine but didn't directly answer the same question I had about reading in a connection string. Through much searching I found a slightly simpler way of doing this.
In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
// Add the whole configuration object here.
services.AddSingleton<IConfiguration>(Configuration);
}
In your controller add a field for the configuration and a parameter for it on a constructor
private readonly IConfiguration configuration;
public HomeController(IConfiguration config)
{
configuration = config;
}
Now later in your view code you can access it like:
connectionString = configuration.GetConnectionString("DefaultConnection");
You can do this with the GetConnectionString extension-method:
string conString = Microsoft
.Extensions
.Configuration
.ConfigurationExtensions
.GetConnectionString(this.Configuration, "DefaultConnection");
System.Console.WriteLine(conString);
or with a structured-class for DI:
public class SmtpConfig
{
public string Server { get; set; }
public string User { get; set; }
public string Pass { get; set; }
public int Port { get; set; }
}
Startup:
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// http://developer.telerik.com/featured/new-configuration-model-asp-net-core/
// services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));
Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<SmtpConfig>(services, Configuration.GetSection("Smtp"));
And then in the home-controller:
public class HomeController : Controller
{
public SmtpConfig SmtpConfig { get; }
public HomeController(Microsoft.Extensions.Options.IOptions<SmtpConfig> smtpConfig)
{
SmtpConfig = smtpConfig.Value;
} //Action Controller
public IActionResult Index()
{
System.Console.WriteLine(SmtpConfig);
return View();
}
with this in appsettings.json:
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplica71d622;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Smtp": {
"Server": "0.0.0.1",
"User": "user#company.com",
"Pass": "123456789",
"Port": "25"
}
See link for more info:
https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-strings
JSON
{
"ConnectionStrings": {
"BloggingDatabase": "Server=(localdb)\\mssqllocaldb;Database=EFGetStarted.ConsoleApp.NewDb;Trusted_Connection=True;"
},
}
C# Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}
EDIT: aspnetcore, starting 3.1:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1
This is how I did it:
I added the connection string at appsettings.json
"ConnectionStrings": {
"conStr": "Server=MYSERVER;Database=MYDB;Trusted_Connection=True;MultipleActiveResultSets=true"},
I created a class called SqlHelper
public class SqlHelper
{
//this field gets initialized at Startup.cs
public static string conStr;
public static SqlConnection GetConnection()
{
try
{
SqlConnection connection = new SqlConnection(conStr);
return connection;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
At the Startup.cs I used ConfigurationExtensions.GetConnectionString to get the connection,and I assigned it to SqlHelper.conStr
public Startup(IConfiguration configuration)
{
Configuration = configuration;
SqlHelper.connectionString = ConfigurationExtensions.GetConnectionString(this.Configuration, "conStr");
}
Now wherever you need the connection string you just call it like this:
SqlHelper.GetConnection();
In .NET Core 6
appsettings.json
"ConnectionStrings": {
"DefaultConnection": "Server=**Server Name**;Database=**DB NAME**;Trusted_Connection=True;MultipleActiveResultSets=true"
}
Program.cs
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString));
DB Context
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
}
The way that I found to resolve this was to use AddJsonFile in a builder at Startup (which allows it to find the configuration stored in the appsettings.json file) and then use that to set a private _config variable
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
_config = builder.Build();
}
And then I could set the configuration string as follows:
var connectionString = _config.GetConnectionString("DbContextSettings:ConnectionString");
This is on dotnet core 1.1
ASP.NET Core (in my case 3.1) provides us with Constructor injections into Controllers, so you may simply add following constructor:
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
private readonly IConfiguration m_config;
public TestController(IConfiguration config)
{
m_config = config;
}
[HttpGet]
public string Get()
{
//you can get connection string as follows
string connectionString = m_config.GetConnectionString("Default")
}
}
Here what appsettings.json may look like:
{
"ConnectionStrings": {
"Default": "YOUR_CONNECTION_STRING"
}
}
In 3.1 there is a section already defined for "ConnectionStrings"
System.Configuration.ConnnectionStringSettings
Define:
"ConnectionStrings": {
"ConnectionString": "..."
}
Register:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ConnectionStringSettings>(Configuration.GetSection("ConnectionStrings"));
}
Inject:
public class ObjectModelContext : DbContext, IObjectModelContext
{
private readonly ConnectionStringSettings ConnectionStringSettings;
...
public ObjectModelContext(DbContextOptions<ObjectModelContext> options, IOptions<ConnectionStringSettings> setting) : base(options)
{
ConnectionStringSettings = setting.Value;
}
...
}
Use:
public static void ConfigureContext(DbContextOptionsBuilder optionsBuilder, ConnectionStringSettings connectionStringSettings)
{
if (optionsBuilder.IsConfigured == false)
{
optionsBuilder.UseLazyLoadingProxies()
.UseSqlServer(connectionStringSettings.ConnectionString);
}
}
The method below will work fine if you want to get a connectionString from appsettings.json into a Model or ViewModel (not Controller). This is for ASP.NET Core 3 and above. Sometimes you may need to get a connectionString into a Model (for SQL queries) rather than dependency injection via the controller so this method below will get your connectionString from appsettings:
public class NameOfYourModel
{
static class getConnection
{
public static IConfigurationRoot Configuration;
public static string GetConnectionString()
{
var builder = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
var connectionString =
Configuration.GetConnectionString("connectionStringName");
return connectionString;
}
}
string connStr = getConnection.GetConnectionString().ToString(); //This
//line now has your connectionString which you can use.
//Continue the rest of your code here.
}
There is another approach. In my example you see some business logic in repository class that I use with dependency injection in ASP .NET MVC Core 3.1.
And here I want to get connectiongString for that business logic because probably another repository will have access to another database at all.
This pattern allows you in the same business logic repository have access to different databases.
C#
public interface IStatsRepository
{
IEnumerable<FederalDistrict> FederalDistricts();
}
class StatsRepository : IStatsRepository
{
private readonly DbContextOptionsBuilder<EFCoreTestContext>
optionsBuilder = new DbContextOptionsBuilder<EFCoreTestContext>();
private readonly IConfigurationRoot configurationRoot;
public StatsRepository()
{
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
configurationRoot = configurationBuilder.Build();
}
public IEnumerable<FederalDistrict> FederalDistricts()
{
var conn = configurationRoot.GetConnectionString("EFCoreTestContext");
optionsBuilder.UseSqlServer(conn);
using (var ctx = new EFCoreTestContext(optionsBuilder.Options))
{
return ctx.FederalDistricts.Include(x => x.FederalSubjects).ToList();
}
}
}
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"EFCoreTestContext": "Data Source=DESKTOP-GNJKL2V\\MSSQLSERVER2014;Database=Test;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Too late, but after reading all helpful answers and comments, I ended up using Microsoft.Extensions.Configuration.Binder extension package and play a little around to get rid of hardcoded configuration keys.
My solution:
IConfigSection.cs
public interface IConfigSection
{
}
ConfigurationExtensions.cs
public static class ConfigurationExtensions
{
public static TConfigSection GetConfigSection<TConfigSection>(this IConfiguration configuration) where TConfigSection : IConfigSection, new()
{
var instance = new TConfigSection();
var typeName = typeof(TConfigSection).Name;
configuration.GetSection(typeName).Bind(instance);
return instance;
}
}
appsettings.json
{
"AppConfigSection": {
"IsLocal": true
},
"ConnectionStringsConfigSection": {
"ServerConnectionString":"Server=.;Database=MyDb;Trusted_Connection=True;",
"LocalConnectionString":"Data Source=MyDb.db",
},
}
To access a strongly typed config, you just need to create a class for that, which implements IConfigSection interface(Note: class names and field names should exactly match section in appsettings.json)
AppConfigSection.cs
public class AppConfigSection: IConfigSection
{
public bool IsLocal { get; set; }
}
ConnectionStringsConfigSection.cs
public class ConnectionStringsConfigSection : IConfigSection
{
public string ServerConnectionString { get; set; }
public string LocalConnectionString { get; set; }
public ConnectionStringsConfigSection()
{
// set default values to avoid null reference if
// section is not present in appsettings.json
ServerConnectionString = string.Empty;
LocalConnectionString = string.Empty;
}
}
And finally, a usage example:
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// some stuff
var app = Configuration.GetConfigSection<AppConfigSection>();
var connectionStrings = Configuration.GetConfigSection<ConnectionStringsConfigSection>();
services.AddDbContext<AppDbContext>(options =>
{
if (app.IsLocal)
{
options.UseSqlite(connectionStrings.LocalConnectionString);
}
else
{
options.UseSqlServer(connectionStrings.ServerConnectionString);
}
});
// other stuff
}
}
To make it neat, you can move above code into an extension method.
That's it, no hardcoded configuration keys.
private readonly IConfiguration configuration;
public DepartmentController(IConfiguration _configuration)
{
configuration = _configuration;
}
[HttpGet]
public JsonResult Get()
{
string sqlDataSource = configuration["ConnectionStrings:DefaultConnection"];
You can use configuration extension method : getConnectionString ("DefaultConnection")
https://docs.asp.net/projects/api/en/latest/autoapi/Microsoft/Extensions/Configuration/ConfigurationExtensions/index.html#Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConnectionString
i have a data access library which works with both .net core and .net framework.
the trick was in .net core projects to keep the connection strings in a xml file named "app.config" (also for web projects), and mark it as 'copy to output directory',
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="conn1" connectionString="...." providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
ConfigurationManager.ConnectionStrings - will read the connection string.
var conn1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;

Categories