Davasorus.Utility.DotNet.Config
2026.2.2.2
See the version list below for details.
dotnet add package Davasorus.Utility.DotNet.Config --version 2026.2.2.2
NuGet\Install-Package Davasorus.Utility.DotNet.Config -Version 2026.2.2.2
<PackageReference Include="Davasorus.Utility.DotNet.Config" Version="2026.2.2.2" />
<PackageVersion Include="Davasorus.Utility.DotNet.Config" Version="2026.2.2.2" />
<PackageReference Include="Davasorus.Utility.DotNet.Config" />
paket add Davasorus.Utility.DotNet.Config --version 2026.2.2.2
#r "nuget: Davasorus.Utility.DotNet.Config, 2026.2.2.2"
#:package Davasorus.Utility.DotNet.Config@2026.2.2.2
#addin nuget:?package=Davasorus.Utility.DotNet.Config&version=2026.2.2.2
#tool nuget:?package=Davasorus.Utility.DotNet.Config&version=2026.2.2.2
Davasorus.Utility.DotNet.Config
Davasorus.Utility.DotNet.Config provides utilities for loading, creating, converting, and updating configuration files (JSON, XML, and YAML) in .NET 8+ applications. It is designed for use with dependency injection (DI) and follows a strict service/client separation: end users should only interact with the Service interfaces; the Service classes handle all client interactions, error handling, and logging.
Features
- Load, create, convert, and update configuration files in JSON, XML, and YAML formats
- Full CRUD operations for each format (Load, Create, Convert, Update)
- Robust error handling and logging (SQS integration)
- Designed for DI: Service = Scoped, Client = Transient
Dependency Injection Setup
Recommended: Fluent API (Simplified)
Use the fluent configuration API to register services easily:
using Tyler.Utility.DotNet.Config.Configuration;
// Register only JSON services (Load, Create, Convert, Update)
services.AddConfigServices(config => config.AddJsonServices());
// Register only XML services (Load, Create, Convert, Update)
services.AddConfigServices(config => config.AddXmlServices());
// Register only YAML services (Load, Create, Convert, Update)
services.AddConfigServices(config => config.AddYamlServices());
// Register all services (JSON + XML + YAML)
services.AddConfigServices(config => config.AddAllServices());
// Or chain them explicitly
services.AddConfigServices(config => config
.AddJsonServices()
.AddXmlServices()
.AddYamlServices());
Alternative: Individual Service Registration
You can also register services individually if you need fine-grained control:
// JSON services
services.AddJsonConfigServices();
// XML services
services.AddXmlConfigServices();
// YAML services
services.AddYamlConfigServices();
// All services
services.AddAllConfigServices();
Manual Registration (Legacy)
If you prefer manual registration:
// JSON
services.AddScoped<ILoadJSONService, LoadJSONService>();
services.AddTransient<ILoadJSONClient, LoadJSONClient>();
services.AddScoped<ICreateJSONService, CreateJSONService>();
services.AddTransient<ICreateJSONClient, CreateJSONClient>();
services.AddScoped<IConvertToJSONService, ConvertToJSONService>();
services.AddTransient<IConvertToJSONClient, ConvertToJSONClient>();
services.AddScoped<IUpdateJSONService, UpdateJSONService>();
services.AddTransient<IUpdateJSONClient, UpdateJSONClient>();
// XML
services.AddScoped<ILoadXmlService, LoadXmlService>();
services.AddTransient<ILoadXMLClient, LoadXMLClient>();
services.AddScoped<ICreateXMLService, CreateXMLService>();
services.AddTransient<ICreateXMLClient, CreateXMLClient>();
services.AddScoped<IConvertToXMLService, ConvertToXMLService>();
services.AddTransient<IConvertToXMLClient, ConvertToXMLClient>();
services.AddScoped<IUpdateXMLService, UpdateXMLService>();
services.AddTransient<IUpdateXMLClient, UpdateXMLClient>();
// YAML
services.AddScoped<ILoadYAMLService, LoadYAMLService>();
services.AddTransient<ILoadYAMLClient, LoadYAMLClient>();
services.AddScoped<ICreateYAMLService, CreateYAMLService>();
services.AddTransient<ICreateYAMLClient, CreateYAMLClient>();
services.AddScoped<IConvertToYAMLService, ConvertToYAMLService>();
services.AddTransient<IConvertToYAMLClient, ConvertToYAMLClient>();
services.AddScoped<IUpdateYAMLService, UpdateYAMLService>();
services.AddTransient<IUpdateYAMLClient, UpdateYAMLClient>();
Note: Only use the Service interfaces (
ILoadJSONService,ICreateJSONService,ILoadXmlService,ILoadYAMLService, etc.) in your application code. The Service classes manage all communication with their respective Client classes internally.
Example Usage
Load JSON File
public class MyConfigLoader
{
private readonly ILoadJSONService _loadJsonService;
public MyConfigLoader(ILoadJSONService loadJsonService)
{
_loadJsonService = loadJsonService;
}
public async Task<MyConfigModel?> LoadConfigAsync(string path, string fileName)
{
return await _loadJsonService.LoadDataFromJsonFile<MyConfigModel>(path, fileName);
}
}
Create JSON File
public class MyConfigCreator
{
private readonly ICreateJSONService _createJsonService;
public MyConfigCreator(ICreateJSONService createJsonService)
{
_createJsonService = createJsonService;
}
public async Task CreateConfigAsync(string path, string fileName, MyConfigModel config)
{
await _createJsonService.CreateJsonFileAsync(path, fileName, config);
}
}
Convert File or Text to JSON
public class MyConverter
{
private readonly IConvertToJSONService _convertToJsonService;
public MyConverter(IConvertToJSONService convertToJsonService)
{
_convertToJsonService = convertToJsonService;
}
public async Task<string?> ConvertFileAsync(string filePath)
{
return await _convertToJsonService.ConvertFileToJsonAsync(filePath);
}
public async Task<string?> ConvertTextAsync(string text)
{
return await _convertToJsonService.ConvertTextToJsonInMemoryAsync(text);
}
}
Update JSON File (Merge, Overwrite, or Add)
public class MyConfigUpdater
{
private readonly IUpdateJSONService _updateJsonService;
public MyConfigUpdater(IUpdateJSONService updateJsonService)
{
_updateJsonService = updateJsonService;
}
// Merge new data into existing JSON file
public async Task UpdateConfigAsync(string path, string fileName, MyConfigModel newData)
{
await _updateJsonService.UpdateJsonFileAsync(path, fileName, newData);
}
// Overwrite JSON file with new data
public async Task OverwriteConfigAsync(string path, string fileName, MyConfigModel newData)
{
await _updateJsonService.OverwriteJsonFileAsync(path, fileName, newData);
}
// Add new data to JSON file (adds new keys only)
public async Task AddToConfigAsync(string path, string fileName, MyConfigModel newData)
{
await _updateJsonService.AddToJSONFileAsync(path, fileName, newData);
}
}
Load XML File
public class MyXmlLoader
{
private readonly ILoadXmlService _loadXmlService;
public MyXmlLoader(ILoadXmlService loadXmlService)
{
_loadXmlService = loadXmlService;
}
// Load and deserialize an XML file
public async Task<MyConfigModel?> LoadConfigAsync(string path, string fileName)
{
return await _loadXmlService.LoadDataFromXmlFile<MyConfigModel>(path, fileName);
}
// Load descendants matching an attribute and value
public async Task<List<XElement>?> LoadDescendantsAsync(string path, string parent, string searchAttribute, string searchValue)
{
return await _loadXmlService.LoadDescendants(path, parent, searchAttribute, searchValue);
}
// Load attributes matching an attribute name
public async Task<List<XAttribute>?> LoadElementsAsync(string path, string parent, string searchAttribute)
{
return await _loadXmlService.LoadElements(path, parent, searchAttribute);
}
}
Create, Convert, and Update XML Files
// Create XML file
await _createXmlService.CreateXmlFileAsync(path, fileName, config);
// Convert file to XML
string? xmlPath = await _convertToXmlService.ConvertFileToXmlAsync(filePath);
// Convert text to XML in memory
string? xml = await _convertToXmlService.ConvertTextToXmlInMemoryAsync(text);
// Update (merge), overwrite, or add to XML file
await _updateXmlService.UpdateXmlFileAsync(path, fileName, data);
await _updateXmlService.OverwriteXmlFileAsync(path, fileName, data);
await _updateXmlService.AddToXmlFileAsync(path, fileName, data);
Load YAML File
public class MyYamlLoader
{
private readonly ILoadYAMLService _loadYamlService;
public MyYamlLoader(ILoadYAMLService loadYamlService)
{
_loadYamlService = loadYamlService;
}
public async Task<MyConfigModel?> LoadConfigAsync(string path, string fileName)
{
return await _loadYamlService.LoadDataFromYamlFile<MyConfigModel>(path, fileName);
}
}
Create, Convert, and Update YAML Files
// Create YAML file
await _createYamlService.CreateYamlFileAsync(path, fileName, config);
// Convert file to YAML
string? yamlPath = await _convertToYamlService.ConvertFileToYamlAsync(filePath);
// Convert text to YAML in memory
string? yaml = await _convertToYamlService.ConvertTextToYamlInMemoryAsync(text);
// Update (merge), overwrite, or add to YAML file
await _updateYamlService.UpdateYamlFileAsync(path, fileName, data);
await _updateYamlService.OverwriteYamlFileAsync(path, fileName, data);
await _updateYamlService.AddToYAMLFileAsync(path, fileName, data);
Error Handling
- All errors are logged using ILogger and SQS.
- Service methods handle exceptions and provide diagnostics.
Requirements
- .NET 8.0 or later
License
MIT License
Upgrade Notes — Group B (2026.2.x → 2026.3.x)
Group B refactors the package's architecture without changing the package's high-level capabilities. Three behaviour changes affect consumers:
1. Reporting goes through IConfigErrorReporter; SQS is auto-detected
ISqsService is no longer a constructor parameter on any Service or Client.
All cross-cutting error reporting goes through the new IConfigErrorReporter
abstraction. Consumers who want to swap in a different reporting sink
(Application Insights, file logger, no-op for tests, etc.) register their
own implementation as IConfigErrorReporter in DI; the package picks it up.
The default registration is automatic and depends on what's already in your DI container:
- If an
ISqsServiceis registered beforeAddJsonConfigServices/AddXmlConfigServices/AddYamlConfigServices/AddAllConfigServices/AddConfigServices(...)runs, the package registersSqsConfigErrorReporteras the default — preserves the pre-Group-B Trello-via-SQS behaviour. - Otherwise, the package registers
NullConfigErrorReporter(no-op) as the default.
In both cases the registration uses TryAddSingleton, so a host-registered
reporter still wins.
Hosts that already had ISqsService registered before Group B keep getting
SQS reporting without changing any DI wiring code. Hosts that want SQS
reporting but are NOT going through one of the Add*ConfigServices
extensions can call services.AddConfigSqsErrorReporter() directly.
2. Every async method gains CancellationToken cancellationToken = default
Source-compatible at call-sites that omit the parameter; binary-incompatible (recompile against the new assembly).
3. Client interfaces split path / Stream methods; path takes (string fullPath)
The most visible breaking change. Each Client's path-based method (Load,
Create, Update, Convert × JSON / XML / YAML) now takes a single
string fullPath argument instead of (string filePath, string fileName).
The two-argument shape stays on Service interfaces. With Group A's
PathSafety.ResolveSafePath validating in the Service layer, the Client
receives a pre-validated, pre-combined full path.
Code that calls Service interfaces (the recommended pattern) is unaffected. Code that calls Client interfaces directly must update:
// Before
client.LoadDataFromJsonFile(filePath, fileName);
// After
client.LoadDataFromJsonFileAsync(Path.Combine(filePath, fileName), cancellationToken);
Each Client also gains parallel Stream overloads on Load / Create / Convert (Update remains path-only). Net-additive surface — no source-compat impact on the Stream side.
4. YAML processing unified on YamlJsonBridge
Group A introduced YamlJsonBridge and routed YAML Convert and YAML
Update through it, but YAML Load and YAML Create still used
YamlDotNet.Serialization.IDeserializer / ISerializer directly with
the camelCase naming convention. Group B finishes the unification — all
four YAML operations now go through YamlJsonBridge + JsonSerializer
with JsonSafety.DefaultReadOptions / DefaultWriteOptions.
Two consumer-visible effects:
- YAML Load matches keys case-insensitively instead of strictly
camelCase-to-PascalCase. Case-insensitive is a superset, so existing
YAML keeps deserializing — and YAML keys whose casing was rejected
before (e.g.
Name: …→ C#Nameproperty) now succeed. - YAML Create writes PascalCase keys instead of camelCase. The byte
contents of newly-written YAML files differ —
Name: Testinstead ofname: Test. Round-tripping through YAML Load works because of the case-insensitive deserialize, but external tooling that reads the YAML directly (linters,yq, other deserializers) sees the new casing. This change brings YAML Create in line with what YAML Convert and YAML Update already produce after Group A.
The behaviour is now consistent across the four YAML operations and matches how the JSON stack handles property names.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Davasorus.Utility.DotNet.Contracts.Types (>= 2026.2.2.1)
- Davasorus.Utility.DotNet.SQS (>= 2026.2.2.2)
- Davasorus.Utility.DotNet.Telemetry (>= 2026.2.2.1)
- Microsoft.Extensions.Logging (>= 10.0.7)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.7)
- YamlDotNet (>= 17.0.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Davasorus.Utility.DotNet.Config:
| Package | Downloads |
|---|---|
|
SA.OpenSearchTool.Business
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.2.2.13 | 0 | 5/15/2026 |
| 2026.2.2.12 | 104 | 5/10/2026 |
| 2026.2.2.11 | 99 | 5/6/2026 |
| 2026.2.2.10 | 92 | 5/5/2026 |
| 2026.2.2.9 | 90 | 5/5/2026 |
| 2026.2.2.8 | 98 | 5/4/2026 |
| 2026.2.2.7 | 84 | 5/4/2026 |
| 2026.2.2.6 | 96 | 5/3/2026 |
| 2026.2.2.5 | 91 | 5/2/2026 |
| 2026.2.2.4 | 104 | 5/2/2026 |
| 2026.2.2.3 | 92 | 5/2/2026 |
| 2026.2.2.2 | 89 | 5/1/2026 |
| 2026.2.2.1 | 97 | 5/1/2026 |
| 2026.2.1.4 | 119 | 4/16/2026 |
| 2026.2.1.3 | 853 | 4/11/2026 |
| 2026.2.1.2 | 141 | 4/9/2026 |
| 2026.2.1.1 | 157 | 4/1/2026 |
| 2026.1.3.5 | 101 | 3/29/2026 |
| 2026.1.3.4 | 109 | 3/24/2026 |
| 2026.1.3.3 | 177 | 3/19/2026 |