{"id":17453526,"url":"https://github.com/jonsequitur/its.configuration","last_synced_at":"2025-04-19T15:39:34.007Z","repository":{"id":23025086,"uuid":"26377669","full_name":"jonsequitur/Its.Configuration","owner":"jonsequitur","description":"App configuration for .NET. Strong-typed, JSON file based, host-independent, and manageable.","archived":false,"fork":false,"pushed_at":"2017-04-24T22:35:43.000Z","size":154,"stargazers_count":24,"open_issues_count":7,"forks_count":13,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-13T01:47:09.892Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonsequitur.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-08T23:02:15.000Z","updated_at":"2023-07-07T15:41:33.000Z","dependencies_parsed_at":"2022-08-21T09:10:40.290Z","dependency_job_id":null,"html_url":"https://github.com/jonsequitur/Its.Configuration","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonsequitur%2FIts.Configuration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonsequitur%2FIts.Configuration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonsequitur%2FIts.Configuration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonsequitur%2FIts.Configuration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonsequitur","download_url":"https://codeload.github.com/jonsequitur/Its.Configuration/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249728874,"owners_count":21316963,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-18T00:43:13.519Z","updated_at":"2025-04-19T15:39:33.991Z","avatar_url":"https://github.com/jonsequitur.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"## App configuration for .NET. Strong-typed, JSON file-based, host-independent, and manageable.\n\n[![Join the chat at https://gitter.im/jonsequitur/Its.Configuration](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jonsequitur/Its.Configuration?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge) [![Build Status](https://ci.appveyor.com/api/projects/status/github/jonsequitur/Its.Configuration?svg=true\u0026branch=master)](https://ci.appveyor.com/project/jonsequitur/its-configuration) [![NuGet Status](http://img.shields.io/nuget/v/Its.Configuration.svg?style=flat)](https://www.nuget.org/packages/Its.Configuration/)\n\nMost bugs in deployed services arise from configuration errors. Configuration in .NET usually consists of code calling ConfigurationManager.AppSettings or RoleEnvironment.GetConfigurationSettingValue to get a keyed value from an XML file, and casting it to an expected type. This tends to fail at a number of points: missing values, unconvertable values, non-obvious default behaviors. Managing configurations for diverse environments tends to amplify these problems. And of course Azure has a different configuration mechanism from vanilla ASP.NET applications.\n\n### Goals\n\nIts.Configuration tries to address a number of common configuration pain points to simplify configuration and make it more robust.\n\n- Management\n  - Reuse configurations across environments or operational modes\n  - Keep groups of configuration values together that belong together\n\n- Robustness and strong-typing\n  - Create settings classes that can guarantee their own internal consistency \n  - Settings classes are plain old C# objects that can define meaningful defaults, expose behavior rather than data, and have unit test coverage.\n\n- Security\n  - Encrypt settings that need to be protected\n  - Separate secrets from keys\n  - Remove the need for your application to know how to decrypt protected settings\n\n- Consistency between Azure and IIS\n  - A single set of configuration files that works regardless of whether you're hosted in a cloud service using .cscfg-based configuration or in vanilla ASP.NET using web.config.\n\n- Testability\n  - Pass settings objects, not primitive values\n  - Establish known-good combinations of configurations during integration tests so that if you need to reconfigure a deployed environment, you can change it to a configuration you've already tested\n\n### Overview\n\n#### A settings class\n\nThe starting point is to take an object-oriented approach to configuration by defining classes for the settings you need:\n\n```csharp\n    public class AzureStorageSettings\n    {\n        public AzureStorageSettings()\n        {\n            NumberOfConnectionRetries = 3;\n        }\n\n        public string BuildConnectionString()\n        {\n            return string.Format(\"DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}\", AccountName, AccountKey);\n        }\n\n        public string AccountName { get; set; }\n\n        public string AccountKey { get; set; }\n\n        public int NumberOfConnectionRetries { get; set; }\n    }\n```\n\nSince `AccountName` and `AccountKey` go together, this approach is bit more organized than having (for example) two separate keys and values in `web.config`. It also allows us to add behavior such as the `BuildConnectionString` method.   \n\n#### The settings values\n\nThe standard setup for your configurations is in a set of files in your project under a folder called `.config`. \n\n```\n\u003cproject root\u003e\n|\n└───\\.config\n    |\n    └───\\internal\n        |\n        └───AzureStorageSettings.json\n    |\n    └───\\local\n    |\n    └───\\production\n        |\n        └───AzureStorageSettings.json\n    |\n    └───\\test    \n```\n\nThese files should be copied to the project output so that they will be included in your deployment. \n\nThe names of these folders are up to you. You can use them to define categories across which some of your configurations might differ, for example environments, data centers, operating modes, testing stages, etc. \n\nThe `.json` files contain JSON that will be deserialized into an instance of your settings class. \n\n```json\n    {\n        \"AccountName\":\"myaccount\",\n        \"AccountKey\":\"ikDE8Xi5CupwkjQyeQud3kltGv8AHVfU6/Nlqe30t==\"\n    }\n```\n\nIn this example, you can see that `NumberOfConnectionRetries` is not set, allowing the class default to be used.\n\nTo access these settings in your code, simply call:\n\n```csharp\n    AzureStorageSettings settings = Settings.Get\u003cAzureStorageSettings\u003e();\n```\n\nThis will look for a file called `AzureStoreSettings.json` (or `AzureStoreSettings.json.secure`) and deserialize its contents into an instance of `AzureStoreSettings`. \n\n#### Precedence\n\nYou'll notice in the screen shot above that there are several folders containing files having the same name. For example, `DiagnosticSettings.json` is found in both the local and production folders. Likewise, there are both `local\\AuthenticationSettings.json` and `production\\AuthenticationSettings.json.secure`, which both deserialize to the `AuthenticationSettings` class.\n\nThe decision of which to use is made based on a configurable settings precedence. In the above example, the precedence used by developers on their local machine would be `local|internal`. This indicates that settings should be looked up first in the `local` folder, then, if not found there, in the `internal` folder. If more than one matching file exists in this lookup path, the first one takes precedence and others are ignored. \n\nThe settings precedence can be set several different ways: \n\nProgrammatically:\n\n```csharp\n    Settings.Precedence = new[] { \"local\", \"internal\" };\n```\n\nIn web.config or app.config:\n\n```xml\n    \u003cappSettings\u003e\n        \u003cadd key=\"Its.Configuration.Settings.Precedence\" value=\"local|internal\" /\u003e\n```\n\nIn Azure configuration (`.cscfg`):\n\n```xml\n    \u003cConfigurationSettings\u003e\n      \u003cSetting name=\"Its.Configuration.Settings.Precedence\" value=\"local|internal\" /\u003e\n```\n\nUsing an environment variable:\n\n```\n    c:\\\u003eset Its.Configuration.Settings.Precedence=local|internal\n```\n\nSo if more than one of these approaches is used, what's _their_ precedence? It's as follows:\n\n1. Programmatic\n2. Environment variable\n3. `.cscfg`\n4. `web.config` / `app.config`\n\nIn practice, for an Azure-deployed web application, this means we set the precedence for local development in web.config, for deployment as an Azure cloud service in the ```.cscfg```, and for deployment to Azure Web Sites using an environment variable set via the Azure Management Portal.\n\nBy changing the precedence setting, you can switch to an entirely different configuration with a single change. Want to debug your production topology locally? Switch the precedence to \"production\" on your local machine.\n\n#### Azure\n\nAs you may have inferred, Its.Configuration is able to read Azure configuration settings. The precedence setting is read using the following method:\n\n```csharp\n    var setting = Settings.AppSetting(\"some-key\");\n```\n\nYou can use this method to directly look up a value from the following settings sources. It will return the first one that matches, in this order:\n\n1. Environment variable\n2. `.cscfg`\n3. `web.config` / `app.config`\n\n#### Security\n\nIf a JSON file's contents are encrypted and `.secure` is appended to the filename, then `Settings.Get\u003cT\u003e()` will transparently decrypt the contents in order to deserialize your settings class. It uses the `System.Security.Cryptography.Pkcs.EnvelopedCms` class. Any certificate found in the local machine/personal certificate store is a candidate. You do not need to specify a certificate, as `EnvelopedCms` handles that.  \n\nThe Its.Configuration command line tool can be used to encrypt and decrypt files. This is mainly a convenience. You can also use `EnvelopedCms` via PowerShell, or use the `Encrypt` and `Decrypt` methods found in `Its.Configuration.CryptographyExtensions`.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonsequitur%2Fits.configuration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonsequitur%2Fits.configuration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonsequitur%2Fits.configuration/lists"}