Skip to content

Instantly share code, notes, and snippets.

@unseensenpai
Last active November 22, 2024 08:09
Show Gist options
  • Save unseensenpai/a16e7f076dec0e91459e8b3e67a5fc8b to your computer and use it in GitHub Desktop.
Save unseensenpai/a16e7f076dec0e91459e8b3e67a5fc8b to your computer and use it in GitHub Desktop.
How To Register App.Config and appsettings.json -> Config Manager for .Net 6+ and ASP.NET Core 6+
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="Bla:Foo:Zoo" value="SampleValue" />
</appSettings>
</configuration>
{
"ConnectionStrings": {
"Default": "123456"
},
"SampleInt": 1234567,
"SampleStringInt": "1234567"
}
[ApiController]
[Route("[Controller]/[Action]")]
public class ConfigController : Controller
{
[HttpGet]
public IList<ConfigKeyValue> GetConfigs()
{
// HOW TO READ CONFIGS ON ASP.NET CORE WEB API (IT HAS OWN DI BUT SOME REASON ITS USABLE FOR IT THO)
return ConfigManager.ConfigurationKeyValues.ToList();
}
}
/// <summary>
/// Static config manager instance.
/// It uses the Microsoft Extensions Configuration engine.
/// It includes methods to access key values in
/// App.config in .Net Framework and appsettings.json in .Net 5+.
/// <para>
/// How To Set:
/// </para>
/// <code>
/// ConfigManager.SetConfiguration(
/// configFilePaths: [
/// new(JsonPath: "appsettings.json", Optional: false, ReloadOnChange: true),
/// new(JsonPath: "config/appsettings.json", Optional: true, ReloadOnChange: true)
/// ],
/// nameValueCollections:
/// [
/// System.Configuration.ConfigurationManager.AppSettings,
/// new System.Collections.Specialized.NameValueCollection() { { "Key1", "true" }, { "Key2", "password123" } }
/// ]
/// );
/// </code>
/// Usage:
/// <para>
/// <code>
/// ConfigManager.Configuration.GetValue("KEYOFCONFIGVALUE");
/// </code>
/// </para>
/// </summary>
public static class ConfigManager
{
/// <summary>
/// Static configuration instance. Use the <seealso cref="SetConfiguration"></seealso> method to set it.
/// </summary>
public static IConfiguration Configuration { get; private set; }
/// <summary>
/// Retrieves previously set config key values with child node(s) if exist as enumerable.
/// </summary>
public static IEnumerable<ConfigKeyValue> ConfigurationKeyValues
{
get =>
IsConfigManagerSet
? Configuration.AsEnumerable().Select(cfg => new ConfigKeyValue(cfg.Key, cfg.Value))
#if NET8_0_OR_GREATER
: [];
#elif NET6_0 || NET7_0
: Enumerable.Empty<ConfigKeyValue>();
#endif
}
/// <summary>
/// Retrieves previously set config key values pairs with child node(s) if exist as enumerable.
/// </summary>
public static IEnumerable<KeyValuePair<string, string>> ConfigurationKeyValuePairs
{
get =>
IsConfigManagerSet
? Configuration.AsEnumerable().Select(cfg => new KeyValuePair<string, string>(cfg.Key, cfg.Value))
#if NET8_0_OR_GREATER
: [];
#elif NET6_0 || NET7_0
: Enumerable.Empty<KeyValuePair<string, string>>();
#endif
}
/// <summary>
/// Serilog KeyValue Pairs
/// </summary>
public static IEnumerable<KeyValuePair<string, string>> GetSerilogKeyValuePairs
{
get => GetKeyValuePairs("serilog:", true);
}
/// <summary>
/// Gets specific config key values via prefix
/// </summary>
/// <param name="configPrefix"></param>
/// <param name="erasePrefixFromKeys">Erased prefix value from keys if true.
/// <para>
/// <code>
/// Key: Serilog:WriteTo - Value: File ->
/// <para>
/// Prefix Serilog ->
/// <para>
/// Key: WriteTo - Value: File
/// </para>
/// </para>
/// </code>
/// </para>
/// </param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<string, string>> GetKeyValuePairs(string configPrefix, bool erasePrefixFromKeys)
{
if (erasePrefixFromKeys)
{
return ConfigurationKeyValues
.Where(k =>
k.Key.StartsWith(configPrefix))
.Select(k =>
new KeyValuePair<string, string>(
k.Key[configPrefix.Length..],
k.Value));
}
else
{
return ConfigurationKeyValues
.Where(k =>
k.Key.StartsWith(configPrefix))
.Select(k =>
new KeyValuePair<string, string>(
k.Key,
k.Value));
}
}
/// <summary>
/// Checks Configuration Set State.
/// </summary>
public static bool IsConfigManagerSet { get => Configuration is not null; }
/// <summary>
/// Throws <see cref="ConfigurationNotSetException"/> if config manager is not set.
/// </summary>
/// <exception cref="ConfigurationNotSetException">Config Manager Is Not Set Exception</exception>
public static void ThrowIfConfigManagerNotSet()
{
if (!IsConfigManagerSet)
throw new ConfigurationNotSetException("Config Manager Is Not Set! Use: ConfigManager.SetConfiguration()");
}
/// <summary>
/// Creates <seealso cref="IConfiguration"/> instance.
/// </summary>
/// <param name="configFilePaths">Json configs (appsettings.json)</param>
/// <param name="nameValueCollections">Xml configs (App.config)</param>
/// <returns></returns>
public static IConfiguration CreateConfiguration(List<JsonConfigSettings> configFilePaths = default, List<NameValueCollection> nameValueCollections = default)
{
ConfigurationBuilder configBuilder = new();
// APPSETTINGS.JSON
if (configFilePaths is not null && configFilePaths.Count > 0)
{
foreach (JsonConfigSettings configFilePath in configFilePaths)
{
configBuilder.AddJsonFile(
path: configFilePath.JsonPath,
optional: configFilePath.Optional,
reloadOnChange: configFilePath.ReloadOnChange);
}
}
// APP.CONFIG
if (nameValueCollections is not null && nameValueCollections.Count > 0)
{
foreach (NameValueCollection nameValueCollection in nameValueCollections)
{
Dictionary<string, string> keyValues = nameValueCollection.AllKeys.ToDictionary(key => key, key => nameValueCollection[key]);
configBuilder.AddInMemoryCollection(keyValues);
}
}
return configBuilder.Build();
}
/// <summary>
/// Sets <seealso cref="Configuration"></seealso> instance.
/// </summary>
/// <param name="configFilePaths">Json configs (appsettings.json)</param>
/// <param name="nameValueCollections">Xml configs (App.config)</param>
/// <returns></returns>
public static void SetConfiguration(List<JsonConfigSettings> configFilePaths = default, List<NameValueCollection> nameValueCollections = default)
{
ConfigurationBuilder configBuilder = new();
// APPSETTINGS.JSON
if (configFilePaths is not null && configFilePaths.Count > 0)
{
foreach (JsonConfigSettings configFilePath in configFilePaths)
{
configBuilder.AddJsonFile(
path: configFilePath.JsonPath,
optional: configFilePath.Optional,
reloadOnChange: configFilePath.ReloadOnChange);
}
}
// APP.CONFIG
if (nameValueCollections is not null && nameValueCollections.Count > 0)
{
foreach (NameValueCollection nameValueCollection in nameValueCollections)
{
Dictionary<string, string> keyValues = nameValueCollection.AllKeys.ToDictionary(key => key, key => nameValueCollection[key]);
configBuilder.AddInMemoryCollection(keyValues);
}
}
Configuration = configBuilder.Build();
}
// TODO Refresh Mechanism see FileSystemWatcher
}
/// <summary>
/// Json file settings object for configuration operations.
/// </summary>
/// <param name="JsonPath">Json config file path with filename</param>
/// <param name="Optional">Is config file optional (If false it throws an error if there is no file in "JsonPath")</param>
/// <param name="ReloadOnChange">Is reload on change</param>
public record JsonConfigSettings(string JsonPath, bool Optional = false, bool ReloadOnChange = true);
/// <summary>
/// Config key value object.
/// </summary>
/// <param name="Key">Config Key</param>
/// <param name="Value">Config Value</param>
public record ConfigKeyValue(string Key, string Value);
/// <summary>
/// ConfigManager configuration not set exception class. <seealso cref="ConfigManager.SetConfiguration(List{JsonConfigSettings}, List{NameValueCollection})"/>
/// </summary>
public class ConfigurationNotSetException : Exception
{
/// <summary>
/// Default constructor without message or inner exception.
/// </summary>
public ConfigurationNotSetException()
{
}
/// <summary>
/// Exception with message.
/// </summary>
/// <param name="message">Error Message</param>
public ConfigurationNotSetException(string message) : base(message)
{
}
/// <summary>
/// Exception with message and inner exception.
/// </summary>
/// <param name="message">Error Message</param>
/// <param name="innerException">Inner Exception</param>
public ConfigurationNotSetException(string message, Exception innerException) : base(message, innerException)
{
}
}
var builder = WebApplication.CreateBuilder(args);
// HOW TO REGISTER ALL CONFIGS TO ASP.NET CORE DI (EITHER APP.CONFIG or APPSETTINGS.JSON)
ConfigManager.SetConfiguration([new("appsettings.json", true, true), new("appsettings.development.json", true, true)])
builder.Configuration.AddInMemoryCollection(ConfigManager.ConfigurationKeyValues.Select(cm => new KeyValuePair<string, string>(cm.Key, cm.Value)));
var app = builder.Build();
app.Run();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
List<ConfigFilePaths> configFilePaths = [
new ConfigFilePaths("appsettings.json", true),
new ConfigFilePaths("Config/appsettings.json"),
new ConfigFilePaths($"appsettings.development.json", true)
];
List<NameValueCollection> nameValueCollections = [System.Configuration.ConfigurationManager.AppSettings];
ConfigManager.SetConfiguration(configFilePaths, nameValueCollections);
}
public WinFormUsage()
{
InitializeComponent();
// SOME USE CASES ON WINFORM FORMS
gridControl1.DataSource = ConfigManager.ConfigurationKeyValues;
string connString = ConfigManager.Configuration.GetConnectionString("Default");
int sampleInt = Convert.ToInt32(ConfigManager.Configuration["SampleInt"]);
int sampleIntWithGetValue = ConfigManager.Configuration.GetValue<int>("SampleInt");
int sampleInt2 = ConfigManager.Configuration.GetValue<int>("SampleStringInt");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment