172

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?

Harsh Patel
  • 47
  • 1
  • 10
motevalizadeh
  • 5,244
  • 14
  • 61
  • 108
  • 1
    https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration – Ravi Teja Mar 10 '17 at 08:27
  • 4
    :D :D This is hilarious. That issue should be simple enough and all I can see is tons of answers, each forking into separate ways. I thought by 2022~2023 things should have been simplified! I landed here looking for an answer, I take off same as I came in, empty handed :) Thank you Microsoft. – Albert Zakhia Jan 08 '23 at 10:06

15 Answers15

142

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");
Brad Patton
  • 4,007
  • 4
  • 34
  • 44
  • 4
    Wouldn't do it like that. If you work without entity framework, you better register a connection factory as singleton, e.g. to use with dapper. You can then still expose a connectionString property if you need to, but I bet it wouldn't be necessary in 99% of cases. – Stefan Steiger Apr 03 '18 at 06:37
  • 4
    But how to access Configuration in Models instead of Controller? – Tanmay Apr 06 '18 at 13:45
  • @Tanmay: You create your Models in such a way that they expect Configuration in the constructor. Then when you create the model in the controller, you pass it Configuration in the constructor. If you call some class in the Controller, which then creates your models, then you need to pass this class the Configuration as well, either in the constructor, or as properties, or as an additional method argument. – Stefan Steiger Sep 12 '18 at 13:02
  • 5
    The more I read and try things, the more I realize getting a connection string is a major undertaking. I just get nulls no matter what I try. – MC9000 Mar 01 '19 at 03:24
  • 18
    Yeah. Too many computer scientists creating huge high hanging fruit just to say "Hello World". Unbelievable. Entropy at it's best. – JustJohn May 16 '19 at 23:25
  • 2
    @JustJohn: I understand your grievance, but proper design is testable, and that means you have to pass dependencies in the constructor, otherwise your application/framework is not unit-testable. This is also proper design, as you can just replace one component with another, without having to change a whole lot of code. If you don't want to pass 100 arguments around, you can also pass the System.IServiceProvider into the class, then you can fetch the dependencies there. But the other side of the coin is that this comes with added complexity. – Stefan Steiger Sep 11 '19 at 11:35
  • 1
    The [Microsoft DI docs](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.1#access-settings-from-a-controller) say the following - 'Generally, don't directly inject IConfiguration into a controller.` I wouldn't suggest this answer for that reason, and instead suggest using the Options pattern as Stefan has posted. – sfors says reinstate Monica Nov 06 '19 at 20:53
  • 1
    Where come from variable Configuration, passed as parameter to "services.AddSingleton" method ? – Bisneto Feb 27 '20 at 14:37
  • @StefanSteiger there's a difference between "proper design" of your own code, though, and something like a connection string which should just be easily available. It's somewhat ridiculous that appsettings.json isn't globally available, that's clearly the entire point of the damn thing. – Jon Story Apr 14 '20 at 17:27
  • 1
    @Jon Story: Oh, should it ? First, confidential information like connection strings should not be accessible in any way where it isn't needed in the first place, for security reasons. Second, if you absolutely want to, you can make it globally available, either by DI, or by just putting it into a static variable/property yourselfs, the framework doesn't do that for you. Third, you should make services that you pass along for data access (e.g. connection factory), instead of passing connection strings. You need the connection string only when you configure the service, at Startup. – Stefan Steiger Apr 16 '20 at 09:43
  • 11
    I agree with @JustJohn, this is unnecessary over-engineering at its finest. Connection strings should be easily available and shouldn't take several hours to implement. There is no need to make everything abstract and wrapped in factories and god knows what else. Some things should always stay simple. – HamsterWithPitchfork Jul 23 '20 at 06:19
  • @Tanmay Logically, services should not be injected to models. You can create desired configuration object inside the service that creates your model, and then pass the configuration object to the model constructor – Efe Oct 29 '20 at 19:08
120

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"
  }
Aran Mulholland
  • 23,555
  • 29
  • 141
  • 228
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
  • 10
    `Configure` is an extension method. It should be used most commonly like this: `services.Configure(Configuration.GetSection("Smtp"));` Sure, it's much the same thing, but I think people not aware will just start doing it the "wrong" way, using the uncommented line, so perhaps best to remove the line. ;) – James Wilkins Mar 13 '17 at 22:52
  • @James Wilkins: Very valid concerns. However, I actually prefer this notation over using it as extension method - this way I know what is being done where, and can copy-paste from 1 place to another, without getting problems because of missing import namespaces. The only problem is, MS uses namespaces for taxonomy instead of name collision prevention - because of that, the namespaces are too long. Also, if you remove the namspaces and use the extension methods, the same kind of people will start complaining about the code not compiling. Not everyone uses an IDE, so it's better this way. – Stefan Steiger Mar 14 '17 at 09:48
  • I find most people don't bother to put the "usings" in their code examples, which is a case for your point, but also why extension methods fail for the other point. ;) – James Wilkins Mar 14 '17 at 18:45
  • @James Wilkins: I completely agree. Usually because they have the using in their code, so they don't know it's an extension method, or because they don't know which of all the using clauses would be needed, so they just post without it. It's getting better with VS 2017, but VS2017 runs only on Windows, plus it's slow (IMHO) - which wouldn't be that bad if it didn't block input, or if starting a debbugger wouldn't take an eternity, but unfortunately, in VS it does. – Stefan Steiger Mar 15 '17 at 06:52
  • Yes, it seems the better VS gets, the slower it gets, perhaps offsetting much of the the extra goodness somewhat, lol. ;) Though sometimes it always seems to get slow up to the initial release before they speed it up (seems to be a trend now). – James Wilkins Mar 15 '17 at 08:10
  • How can you get the connectionString in your model? Is there some shortcut or is the only way trough injection? – tedi Oct 05 '17 at 11:52
  • 4
    @JedatKinports: No, only injection. Even if you'd write a static method, you'd still need the configuration. You could just read a JSON/YAML file manually, though. But that will eliminate overwrites, such as usersecrets or others (e.g. configuration from registry). – Stefan Steiger Feb 21 '18 at 08:19
  • 3
    I am getting an error: "MyClass does contain a definition for 'Configuration'..." – Robert Smith Oct 18 '18 at 18:49
  • 5
    What is "this.Configuration" referring to in the connection string part? GetConnectionString(this.Configuration, "DefaultConnection") – MC9000 Sep 22 '19 at 04:24
  • @MC9000: The IConfiguration property in the startup class (which gets passed in in the constructor). IConfiguration comes from reading the appsettings.json file, where you have a section "ConnectionString". – Stefan Steiger Sep 23 '19 at 10:59
  • 1
    Amazing. And for ConnectionString, which is the question about, how to do it? – Bisneto Feb 27 '20 at 14:30
  • @Bisneto: Well, you have several options. The simplest and most atrocious is of course, putting IConfiguration into a static variable. Then you can call GetConnectionString on it wherever you like. However, the smart approch is reading the connection string once, and create a factory class and get the connection string within the factory, once, or if the change token of the config file changes. Then register the factory class in ConfigureServices, and then you don't need to get the connection string at all, or your factory class can expose the connection string as property. – Stefan Steiger Feb 27 '20 at 15:12
  • @Bisneto: Actually, the question demonstrates a lack of understanding of Dependency Injection. You don't want a connection string. You want a connection-factory registered as a service. Also, IConfiguration can change (it has a change-token), a static string is bad. See also: Microsoft.Extensions.Primitives.ChangeToken.OnChange - and for an example, see https://github.com/dotnet/runtime/issues/32735 – Stefan Steiger Feb 28 '20 at 08:53
  • How about if you want to get the `ConnectionString` from an appSettings.json file that resides in a UnitTest .net Core project, where you don't have direct access to `IConfiguration`? – Cristian Rusanu Sep 20 '20 at 20:11
  • 2Cristian: Like this (you might want to create a DI service): string json = System.IO.File.ReadAllText("/path/appsettings.json", System.Text.Encoding.UTF8); Newtonsoft.Json.JsonConvert.DeserializeObject(json); – Stefan Steiger Sep 21 '20 at 07:53
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

markokstate
  • 923
  • 2
  • 14
  • 28
17

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)
    {

    }

}
Sumith Ekanayake
  • 1,741
  • 17
  • 13
  • 1
    Thanks for clarifying, this is so vital - `builder.Configuration.GetConnectionString("DefaultConnection");` it is indeed different in .Net 6 sdk. – JaisG Apr 09 '22 at 19:41
  • I recommend against MARS (multiple active result sets) because this can cause many round-trips to the database, which can be a difficult-to-diagnose performance issue. – Eric J. Sep 10 '22 at 21:35
14

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();
G3n1t0
  • 198
  • 1
  • 10
9

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

Alex White
  • 1,486
  • 16
  • 22
7

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"
        }
}
antonpv
  • 807
  • 1
  • 10
  • 9
3

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);
        }
    }
Craig
  • 344
  • 4
  • 9
3

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.
}
Jeff
  • 115
  • 7
2

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"
  }
}
NoWar
  • 36,338
  • 80
  • 323
  • 498
1

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.

Efe
  • 800
  • 10
  • 32
0
private readonly IConfiguration configuration;
        public DepartmentController(IConfiguration _configuration)
        {
            configuration = _configuration;
        }

        [HttpGet]
        public JsonResult Get()
        {
string sqlDataSource = configuration["ConnectionStrings:DefaultConnection"];
Anindya
  • 2,616
  • 2
  • 21
  • 25
0

This answer is similar to other but a little more straight forward.
Tested in .NET Core 6.
Assuming connection string in appsettings.json like this.

"ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\xxx"
    "Connect_2": "Data Source=((SERVICE_NAMEXXX"
}

var builder = new ConfigurationBuilder();

builder.AddJsonFile("appsettings.json");

IConfiguration configuration = builder.Build();
string _connstr = configuration.GetConnectionString("DefaultConnection");
string _connstr2 = configuration.GetConnectionString("Connect_2");`

_connstr will hold "Server=(localdb)\xxx".
_connstr2 will hold "Data Source=((SERVICE_NAMEXXX".

code-it
  • 81
  • 4
-1

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;
shaig
  • 35
  • 4
  • 1
    If you're using .NET Core, it's best to adopt its configuration pattern instead of shoehorning in the .NET Framework pattern. – Simmetric Jul 07 '20 at 13:44
-2

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

Ivano Scifoni
  • 15
  • 1
  • 3