{"id":53545,"date":"2020-09-01T08:00:16","date_gmt":"2020-09-01T06:00:16","guid":{"rendered":"https:\/\/code-maze.com\/?p=53545"},"modified":"2021-12-27T13:50:05","modified_gmt":"2021-12-27T12:50:05","slug":"aspnet-configuration-basic-concepts","status":"publish","type":"post","link":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/","title":{"rendered":"ASP.NET Core Configuration &#8211; Basic Concepts"},"content":{"rendered":"<p>In this introductory article, we are going to learn how ASP.NET Core configuration works, the basic configuration concepts, and a few different ways we can use to configure our application. Even by default, the configuration mechanism in .NET is pretty powerful, but it has a lot of advanced mechanisms that make it even more so.<\/p>\n<p>Once we go through the basic concepts, we&#8217;ll tackle some of the advanced ones, but for now, let&#8217;s just see what comes out of the box when we create an ASP.NET Core project.<\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">The source code for this article can be found on the <a href=\"https:\/\/github.com\/CodeMazeBlog\/aspnet-core-configuration\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ASP.NET Core Configuration repo on GitHub<\/a>. If you wish to follow along, use the <a href=\"https:\/\/github.com\/CodeMazeBlog\/aspnet-core-configuration\/tree\/start\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">start<\/a> branch. To check out the finished source code, check out the <a href=\"https:\/\/github.com\/CodeMazeBlog\/aspnet-core-configuration\/tree\/basic-concepts\">basic concepts<\/a> branch.<\/div>\n<p>Let&#8217;s dive in.<\/p>\n<h2><a id=\"configuration\"><\/a>What is Configuration?<\/h2>\n<p>Application configuration is a way of providing the <strong>initial settings to our application on its startup<\/strong>. We use configuration to easily set up our application in different ways, usually depending on the environment that it&#8217;s deployed on.<\/p>\n<p>Configuration may come from <strong>multiple different sources and in a wide variety of forms<\/strong> like files, environment variables, or some kind of store like Azure Key Vault, or even from in-memory storage or as command-line arguments.<\/p>\n<p>Whichever way(s) we choose, the configuration mechanism exists to help us create <strong>flexible applications, without the need to recompile our source code<\/strong>. By using the configuration data we determine the behavior of our applications at runtime.<\/p>\n<p>Configuration in .NET Core is pretty powerful and it can be easily installed and used. The NuGet package containing the configuration is <code>Microsoft.Extensions.Configuration<\/code> and you can easily add it to any .NET Core project by typing:<\/p>\n<p><code>PM&gt; Install-Package Microsoft.Extensions.Configuration<\/code> in the Package Manager Console in Visual Studio or<br \/>\n<code>dotnet add package Microsoft.Extensions.Configuration<\/code> if you prefer the dotnet CLI.<\/p>\n<p>If you create an ASP.NET Core application, you don&#8217;t have to worry about it since it&#8217;s <strong>referenced by default<\/strong>.<\/p>\n<p>Configuration in .NET Core is even more powerful with the use of <strong>sections, configuration providers, and the Options pattern<\/strong>. We&#8217;ll talk about all of these concepts in this article, as well as later on.<\/p>\n<h2><a id=\"definition\"><\/a>How do We Define Configuration Data?<\/h2>\n<p>Configuration data is defined as a set of key-value pairs.<\/p>\n<p>Values can be:<\/p>\n<ul>\n<li><strong>integers<\/strong> &#8211; can be any integer number, used when we need a numerical value, like the maximum number of items, or a default temperature for example<br \/>\n<code>DefaultRoomTemperature = 21<\/code><\/li>\n<li><strong>booleans<\/strong> &#8211; can be true or false. Used often to determine if a behavior should be triggered or not within our application<br \/>\n<code>TurnOnDetailedReports = true<\/code><\/li>\n<li><strong>strings<\/strong> &#8211; if we need a specific string value. Typical examples, but not limited to these are connection strings and URLs<br \/>\n<code><span class=\"pl-s\">sqlConnection<span class=\"pl-pds\">\u00a0=<\/span><\/span>\u00a0<span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>server=.; database=AccountOwnerDatabase; Integrated Security=true<span class=\"pl-pds\">\"<\/span><\/span><\/code><\/li>\n<\/ul>\n<p>These are just examples and besides a value, each key contains information about which level of the hierarchy it&#8217;s in.<\/p>\n<p>Let&#8217;s see what that means.<\/p>\n<h2><a id=\"hierarchy\"><\/a>Hierarchical Data Organization and Data Flattening<\/h2>\n<p>The Configuration API reads the hierarchical data by flattening the structure using delimiters.<\/p>\n<p>This means we can write something like this in our configuration file:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"Hierarchical configuration data\" data-enlighter-language=\"json\">{\r\n\t\"Logging\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Information\",\r\n\t\t\t\"Microsoft\": \"Warning\",\r\n\t\t\t\"Microsoft.Hosting.Lifetime\": \"Information\"\r\n\t\t}\r\n\t},\r\n\t\"AllowedHosts\": \"*\"\r\n}\r\n<\/pre>\n<p>And later on, access it in our code by using the semicolon delimiter &#8220;:&#8221;.<\/p>\n<p>Examples:<\/p>\n<p><code>\"Logging:LogLevel:Default\"<\/code> &#8211; We can get the Default logging level<br \/>\n<code>\"AllowedHosts\"<\/code> &#8211; We&#8217;ll get &#8220;*&#8221; (any host) in this case<\/p>\n<p>This means we can have multiple keys named &#8220;Default&#8221; since the organization is hierarchical.<\/p>\n<p>Let&#8217;s extend our example:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"Same key, different hierarchy\" data-enlighter-language=\"json\">{\r\n\t\"Logging\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Information\",\r\n\t\t\t\"Microsoft\": \"Warning\",\r\n\t\t\t\"Microsoft.Hosting.Lifetime\": \"Information\"\r\n\t\t}\r\n\t},\r\n\t\"OtherLoggingProvider\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Debug\"\r\n\t\t}\r\n\t},\r\n\t\"AllowedHosts\": \"*\"\r\n}<\/pre>\n<p>Now we can access the same key within the different hierarchy:<\/p>\n<p><code>\"Logging:LogLevel:Default\"<\/code> &#8211; returns &#8220;Information&#8221;<br \/>\n<code>\"OtherLoggingProvider:LogLevel:Default\"<\/code> &#8211; returns &#8220;Debug&#8221;<\/p>\n<p>If the value doesn&#8217;t exist, we&#8217;ll get a null as a result.<\/p>\n<p>Instead of accessing the values directly, using delimiters, we can use the <strong>options pattern<\/strong>, and <code>GetSection()<\/code> and <code>GetChildren()<\/code> methods to get sections and children of a section. These mechanisms make the configuration much easier to use. We&#8217;ll see how to use them later on.<\/p>\n<p>Let&#8217;s see what we get out of the box when we create an ASP.NET Core application.<\/p>\n<h2><a id=\"default\"><\/a>Default ASP.NET Core Configuration<\/h2>\n<p>When we create a new ASP.NET Core application, our Program.cs file looks like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class Program\r\n{\r\n    public static void Main(string[] args)\r\n    {\r\n        CreateHostBuilder(args).Build().Run();\r\n    }\r\n\r\n    public static IHostBuilder CreateHostBuilder(string[] args) =&gt;\r\n        Host.CreateDefaultBuilder(args)\r\n            .ConfigureWebHostDefaults(webBuilder =&gt;\r\n            {\r\n                webBuilder.UseStartup&lt;Startup&gt;();\r\n            });\r\n}<\/pre>\n<p>While it may not look that spectacular, this does a few things for us. The <code>CreateDefaultBuilder()<\/code> method is particularly interesting to us.<\/p>\n<p>It creates an instance of a <code>HostBuilder<\/code>, which implements <code>IHostBuilder<\/code> and that&#8217;s our program initialization utility. Besides that, it populates it with some default values, some of which are the default values gathered from different sources.<\/p>\n<p>The CreateDefaultBuilder() method adds the default configuration values to the application in this particular order:<\/p>\n<ul>\n<li><strong>ChainedConfigurationProvider<\/strong> &#8211; adds the <em>host<\/em> <code>IConfiguration<\/code> to the <em>app<\/em> <code>IConfiguration<\/code><\/li>\n<li><strong>appsettings.json file<\/strong> &#8211; this is the default file we get when creating an ASP.NET Core template<\/li>\n<li><strong>appsettings.{EnvironmentName}.json files<\/strong> &#8211; for the environment-specific overrides<\/li>\n<li><strong>App Secrets<\/strong> when the <code>EnvironmentName<\/code> variable is set to &#8220;Development&#8221;<\/li>\n<li><strong>Environment variables<\/strong><\/li>\n<li><strong>Command-line arguments<\/strong><\/li>\n<\/ul>\n<p>These key-value pairs are stored inside the <code>IConfiguration<\/code>, and it plays a big role in our application later on.<\/p>\n<p>Now that we know how the default configuration is populated in our application, let&#8217;s see how we can read it at runtime.<\/p>\n<h2><a id=\"readingvalues\"><\/a>Reading Values at Runtime<\/h2>\n<p>After a bit of theory, let&#8217;s do some coding.<\/p>\n<p>First of all, we need a way to access our values.<\/p>\n<p>Since <a href=\"https:\/\/code-maze.com\/dependency-injection-aspnet\/\" target=\"_blank\" rel=\"noopener noreferrer\">dependency injection<\/a> is turned on by default in our application we can do it simply by injecting our <code>IConfiguration<\/code> interface in our controller (or anywhere else). So let&#8217;s do exactly that. Let&#8217;s inject <code>IConfiguration<\/code> into the <code>HomeController<\/code> class.<\/p>\n<p>When we open the <code>HomeController<\/code>, we can immediately see that the <code>ILogger<\/code> is already injected into the constructor:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"HomeController.cs\" data-enlighter-language=\"csharp\">private readonly ILogger&lt;HomeController&gt; _logger;\r\n\r\npublic HomeController(ILogger&lt;HomeController&gt; logger)\r\n{\r\n    _logger = logger;\r\n}<\/pre>\n<p>We can inject IConfiguration in exactly the same manner:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"Injecting IConfiguration\" data-enlighter-language=\"csharp\">private readonly ILogger&lt;HomeController&gt; _logger;\r\nprivate readonly IConfiguration _configuration;\r\n\r\npublic HomeController(ILogger&lt;HomeController&gt; logger, IConfiguration configuration)\r\n{\r\n    _logger = logger;\r\n    _configuration = configuration;\r\n}<\/pre>\n<p>Now we can use the <code>_configuration<\/code> variable to access our values in the entire controller. Let&#8217;s create a dummy model first to populate it with our data. Let&#8217;s navigate to the Model folder and create a <code>HomeModel<\/code> class. This will be a simple class with a single property <code>DefaultLogLevel<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"HomeModel\" data-enlighter-language=\"csharp\">public class HomeModel\r\n{\r\n    public string DefaultLogLevel { get; set; }\r\n}<\/pre>\n<p>Let&#8217;s return to our controller, read our configuration, and send the data to our Home Index view:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public IActionResult Index()\r\n{\r\n    var homeModel = new HomeModel\r\n    {\r\n        DefaultLogLevel = _configuration.GetValue&lt;string&gt;(\"Logging:LogLevel:Default\")\r\n    };\r\n    return View(homeModel);\r\n}<\/pre>\n<p>And change our Home Index.html a bit:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"Home Index.html\" data-enlighter-language=\"html\">@{\r\n    ViewData[\"Title\"] = \"Home Page\";\r\n}\r\n\r\n&lt;div class=\"text-center\"&gt;\r\n    &lt;h1 class=\"display-4\"&gt;Welcome&lt;\/h1&gt;\r\n    &lt;span&gt;Our default logging level is &lt;\/span&gt;&lt;strong&gt;@Model.DefaultLogLevel&lt;\/strong&gt;\r\n    &lt;p&gt;Learn about &lt;a href=\"https:\/\/docs.microsoft.com\/aspnet\/core\"&gt;building Web apps with ASP.NET Core&lt;\/a&gt;.&lt;\/p&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<p>Sure enough, our application now displays our configuration value:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/2020-07-26-21_14_23-Window.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-53553 size-full\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/2020-07-26-21_14_23-Window-e1595791103705.png\" alt=\"configuration home index\" width=\"456\" height=\"141\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/2020-07-26-21_14_23-Window-e1595791103705.png 456w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/2020-07-26-21_14_23-Window-e1595791103705-300x93.png 300w\" sizes=\"auto, (max-width: 456px) 100vw, 456px\" \/><\/a><\/p>\n<p>As you can see, we&#8217;ve used a strongly typed <code>GetValue()<\/code> method to read our default logging level, using the same principle as before to navigate the hierarchy.<\/p>\n<p>It&#8217;s as easy as that.<\/p>\n<h2><a id=\"sections\"><\/a>Configuration Sections<\/h2>\n<p>The <code>GetSection()<\/code> method helps us further by isolating separate sections or subsections of our configuration. To put that into perspective let&#8217;s look at our example once again:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"apsettings.json\" data-enlighter-language=\"json\">{\r\n\t\"Logging\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Information\",\r\n\t\t\t\"Microsoft\": \"Warning\",\r\n\t\t\t\"Microsoft.Hosting.Lifetime\": \"Information\"\r\n\t\t}\r\n\t},\r\n\t\"OtherLoggingProvider\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Debug\"\r\n\t\t}\r\n\t},\r\n\t\"AllowedHosts\": \"*\"\r\n}\r\n<\/pre>\n<p>In this case, &#8220;Logging&#8221; would be a section, and &#8220;LogLevel&#8221; is a subsection. Since we need just the LogLevel data, we can isolate it by returning just the LogLevel subsection in our HomeController Index action:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public IActionResult Index()\r\n{\r\n    var logLevelSection = _configuration.GetSection(\"Logging:LogLevel\");\r\n\r\n    var homeModel = new HomeModel\r\n    {\r\n        DefaultLogLevel = logLevelSection.GetValue&lt;string&gt;(\"Default\")\r\n    };\r\n\r\n    return View(homeModel);\r\n}<\/pre>\n<p>The result is the same as before.<\/p>\n<p>Although this is a small example, imagine more complex settings file like we see every day in a real-world project. It contains a lot of different sections, for various parts of our application. Getting sections and organizing them logically would be a crucial task to make our application more readable, and less dependent on hard coded strings.<\/p>\n<p>A common usage of the <code>GetSection()<\/code> method can be seen in the extension method <code>GetConnectionString()<\/code>.<\/p>\n<p>Let&#8217;s load it from the assembly:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"GetConnectionString method\" data-enlighter-language=\"csharp\">public static string GetConnectionString(this IConfiguration configuration, string name)\r\n{\r\n    return configuration?.GetSection(\"ConnectionStrings\")?[name];\r\n}<\/pre>\n<p>We can see that it&#8217;s just the implementation of the GetSection() method. It takes a name of the connection string and then tries to find it within the &#8220;ConnectionStrings&#8221; section.<\/p>\n<p>That&#8217;s why our connection strings should be located within that section inside our appsettings.json file:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"appsetting.json\" data-enlighter-language=\"json\">{\r\n\t\"Logging\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Information\",\r\n\t\t\t\"Microsoft\": \"Warning\",\r\n\t\t\t\"Microsoft.Hosting.Lifetime\": \"Information\"\r\n\t\t}\r\n\t},\r\n\t\"ConnectionStrings\": {\r\n\t\t\"sqlConnection\": \"server=.; database=CodeMazeCommerce; Integrated Security=true\"\r\n\t},\r\n\t\"OtherLoggingProvider\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Debug\"\r\n\t\t}\r\n\t},\r\n\t\"AllowedHosts\": \"*\"\r\n}\r\n<\/pre>\n<p>We can get the string as easy as this now:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"GetConnectionString application\" data-enlighter-language=\"csharp\">Configuration.GetConnectionString(\"sqlConnection\");<\/pre>\n<p>Awesome!<\/p>\n<p>We recommend that you use a similar pattern to get other sections of your configuration. If you are not familiar with extension methods check out <a href=\"https:\/\/code-maze.com\/csharp-static-members-constants-extension-methods\/#extensionmethods\" target=\"_blank\" rel=\"noopener noreferrer\">our article<\/a> on them to learn how they work.<\/p>\n<h2><a id=\"binding\"><\/a>Binding Configuration<\/h2>\n<p>We&#8217;ve seen how we can extract our configuration data by using <code>IConfiguration<\/code>. But it does have its flaws.<\/p>\n<p>Having to type sections and keys to get the values can be really repetitive and error-prone. We risk introducing errors to our code, and these kinds of errors can cost us a lot of time until we discover them since someone else can introduce them, and we won&#8217;t notice them since a null result is returned when values are missing.<\/p>\n<p>To overcome this problem, we can bind the configuration data to strongly typed objects. To do that, we can use the <code>Bind()<\/code> method.<\/p>\n<p>We can quickly create a simple container class for the configuration called <code>LoggingLevelConfiguration<\/code>, inside our Model folder:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"LoggingLevelConfiguration\" data-enlighter-language=\"csharp\">public class LoggingLevelConfiguration\r\n{\r\n    public string Default { get; set; }\r\n}<\/pre>\n<p>And now, let&#8217;s make some changes to our <code>HomeController<\/code> <code>Index()<\/code> method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public IActionResult Index()\r\n{\r\n    var logLevelConfiguration = new LoggingLevelConfiguration();\r\n\r\n    _configuration.Bind(\"Logging:LogLevel\", logLevelConfiguration);\r\n\r\n    var homeModel = new HomeModel\r\n    {\r\n        DefaultLogLevel = logLevelConfiguration.Default\r\n    };\r\n\r\n    return View(homeModel);\r\n}<\/pre>\n<p>And once again, we can run the project and make sure that result is the same.<\/p>\n<p>As you can see, instead of using <code>GetValue()<\/code> or <code>GetSection()<\/code> methods we&#8217;ve bound our configuration data to the <code>LoggingLevelConfiguration<\/code> section directly, and we&#8217;re accessing the configuration data by calling the <code>Default<\/code> property of that class.<\/p>\n<p>Pretty neat, huh?<\/p>\n<p>There are two things to note here though. First is that the names of the configuration data keys and class properties must match. The other is that if you extend the configuration, you need to extend the class as well, which can be a bit cumbersome, but it beats getting values by typing strings.<\/p>\n<h2><a id=\"environment\"><\/a>Creating an Environment Specific Configuration<\/h2>\n<p>Any application that is meant to go to the production has at least two environments &#8211; development and production. Besides that, we can have other environments, like staging which is an environment where we can check if the application is working correctly before we deploy it to production.<\/p>\n<p>Check out our article about using <a href=\"https:\/\/code-maze.com\/multiple-environments-in-asp-net-core\/\">multiple environments in ASP.NET Core<\/a> to learn about it in more detail.<\/p>\n<p>As you might have noticed, our project template has two appsettings files. One is the default appsettings.json file, and another is appsettings.<strong>Development<\/strong>.json. In this file, we can override any value from the appsettings.json file and it will be used when we are working in the development environment.<\/p>\n<p>The practical example of the usage would be having different configuration strings for production and development since we don&#8217;t want to mess up the production database during development.<\/p>\n<p>For example, this would be a connection string for the development:<\/p>\n<pre class=\"EnlighterJSRAW\" title=\"apsettings.json\" data-enlighter-language=\"json\" data-enlighter-highlight=\"9-11\">{\r\n\t\"Logging\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Information\",\r\n\t\t\t\"Microsoft\": \"Warning\",\r\n\t\t\t\"Microsoft.Hosting.Lifetime\": \"Information\"\r\n\t\t}\r\n\t},\r\n\t\"ConnectionStrings\": {\r\n\t\t\"sqlConnection\": \"server=.; database=CodeMazeCommerce; Integrated Security=true\"\r\n\t},\r\n\t\"OtherLoggingProvider\": {\r\n\t\t\"LogLevel\": {\r\n\t\t\t\"Default\": \"Debug\"\r\n\t\t}\r\n\t},\r\n\t\"AllowedHosts\": \"*\"\r\n}<\/pre>\n<p>And now we can create an appsettings.Production.json file in which we will change the connection string to something else:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{\r\n\t\"ConnectionStrings\": {\r\n\t\t\"sqlConnection\": \"server=ProductionServerName; database=CodeMazeCommerce; Integrated Security=true\"\r\n\t}\r\n}<\/pre>\n<p>That&#8217;s it. Once the application is running in the production environment (indicated by the <code>ASPNETCORE_ENVIRONMENT<\/code> environment variable), the production string from the apsettings.Production.json will be used instead of the default one.<\/p>\n<h2><a id=\"conclusion\"><\/a>Conclusion<\/h2>\n<p>In this article, we&#8217;ve gone through some basic concepts of ASP.NET Core application configuration. We&#8217;ve learned how to use change configuration settings for our application, use sections to logically group our configuration data, and read the hierarchical configuration structures.<\/p>\n<p>We still haven&#8217;t touched upon the <a href=\"https:\/\/code-maze.com\/aspnet-configuration-options\/\" target=\"_blank\" rel=\"noopener noreferrer\">options pattern<\/a> or <a href=\"https:\/\/code-maze.com\/aspnet-configuration-providers\/\" target=\"_blank\" rel=\"noopener noreferrer\">configuration providers<\/a>, which are our next topics of this <a href=\"https:\/\/code-maze.com\/net-core-series\/#configuration\" target=\"_blank\" rel=\"noopener noreferrer\">series<\/a>.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this introductory article, we are going to learn how ASP.NET Core configuration works, the basic configuration concepts, and a few different ways we can use to configure our application. Even by default, the configuration mechanism in .NET is pretty powerful, but it has a lot of advanced mechanisms that make it even more so. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":54346,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[12],"tags":[10,79,730,146],"class_list":["post-53545","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-csharp","tag-net","tag-asp-net-core","tag-basic","tag-configuration","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>ASP.NET Core Configuration - Basic Concepts - Code Maze<\/title>\n<meta name=\"description\" content=\"In this introductory article, we are going to learn how ASP.NET Core configuration works and cover the basic configuration concepts.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ASP.NET Core Configuration - Basic Concepts - Code Maze\" \/>\n<meta property=\"og:description\" content=\"In this introductory article, we are going to learn how ASP.NET Core configuration works and cover the basic configuration concepts.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2020-09-01T06:00:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-12-27T12:50:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Vladimir Pecanac\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/PecanacVladimir\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Vladimir Pecanac\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/\"},\"author\":{\"name\":\"Vladimir Pecanac\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739\"},\"headline\":\"ASP.NET Core Configuration &#8211; Basic Concepts\",\"datePublished\":\"2020-09-01T06:00:16+00:00\",\"dateModified\":\"2021-12-27T12:50:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/\"},\"wordCount\":1798,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png\",\"keywords\":[\".NET\",\"asp.net core\",\"Basic\",\"configuration\"],\"articleSection\":[\"C#\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/\",\"url\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/\",\"name\":\"ASP.NET Core Configuration - Basic Concepts - Code Maze\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png\",\"datePublished\":\"2020-09-01T06:00:16+00:00\",\"dateModified\":\"2021-12-27T12:50:05+00:00\",\"description\":\"In this introductory article, we are going to learn how ASP.NET Core configuration works and cover the basic configuration concepts.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png\",\"width\":1100,\"height\":620,\"caption\":\"configuration basic concepts\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"ASP.NET Core Configuration &#8211; Basic Concepts\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739\",\"name\":\"Vladimir Pecanac\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png\",\"caption\":\"Vladimir Pecanac\"},\"description\":\"Hi, my name is Vladimir Pecanac, and I am a full-time .NET developer and DevOps enthusiast. I created this blog so I can share the things I learn in the hope of both helping others and deepening my own knowledge of the topics I write about. The best way to learn is to teach.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/vladimir-pecanac\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/PecanacVladimir\"],\"url\":\"https:\/\/code-maze.com\/author\/codemaze_blog\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"ASP.NET Core Configuration - Basic Concepts - Code Maze","description":"In this introductory article, we are going to learn how ASP.NET Core configuration works and cover the basic configuration concepts.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/","og_locale":"en_US","og_type":"article","og_title":"ASP.NET Core Configuration - Basic Concepts - Code Maze","og_description":"In this introductory article, we are going to learn how ASP.NET Core configuration works and cover the basic configuration concepts.","og_url":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/","og_site_name":"Code Maze","article_published_time":"2020-09-01T06:00:16+00:00","article_modified_time":"2021-12-27T12:50:05+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png","type":"image\/png"}],"author":"Vladimir Pecanac","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/PecanacVladimir","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Vladimir Pecanac","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/"},"author":{"name":"Vladimir Pecanac","@id":"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739"},"headline":"ASP.NET Core Configuration &#8211; Basic Concepts","datePublished":"2020-09-01T06:00:16+00:00","dateModified":"2021-12-27T12:50:05+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/"},"wordCount":1798,"commentCount":2,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png","keywords":[".NET","asp.net core","Basic","configuration"],"articleSection":["C#"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/","url":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/","name":"ASP.NET Core Configuration - Basic Concepts - Code Maze","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png","datePublished":"2020-09-01T06:00:16+00:00","dateModified":"2021-12-27T12:50:05+00:00","description":"In this introductory article, we are going to learn how ASP.NET Core configuration works and cover the basic configuration concepts.","breadcrumb":{"@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/configuration-basic-concepts.png","width":1100,"height":620,"caption":"configuration basic concepts"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/aspnet-configuration-basic-concepts\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"ASP.NET Core Configuration &#8211; Basic Concepts"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739","name":"Vladimir Pecanac","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png","caption":"Vladimir Pecanac"},"description":"Hi, my name is Vladimir Pecanac, and I am a full-time .NET developer and DevOps enthusiast. I created this blog so I can share the things I learn in the hope of both helping others and deepening my own knowledge of the topics I write about. The best way to learn is to teach.","sameAs":["https:\/\/www.linkedin.com\/in\/vladimir-pecanac\/","https:\/\/x.com\/https:\/\/twitter.com\/PecanacVladimir"],"url":"https:\/\/code-maze.com\/author\/codemaze_blog\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/53545","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=53545"}],"version-history":[{"count":1,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/53545\/revisions"}],"predecessor-version":[{"id":62236,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/53545\/revisions\/62236"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/54346"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=53545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=53545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=53545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}