Dans cet article, nous allons voir comment injecter proprement la configuration dans une application .NET en tirant parti du système d’injection de dépendances. À partir d’un simple fichier appsettings.json, nous verrons comment lier des sections de configuration à des classes typées, les enregistrer au démarrage de l’application, puis les consommer dans des services via le pattern Options
Principe :
- Les valeurs de configuration sont chargées au démarrage (ex: via
IConfiguration). - On peut injecter
IConfigurationou des objets typés (pattern Options) dans les classes (contrôleurs, services, handlers, etc.).
Exemple simple
Soit le fichier de configuration suivant
{
"CheminOption": {
"MonOption": "valeur"
}
}
Et la classe correspondante de sérialisation Json
public class MySettings
{
public const string Path = "CheminOption";
public string MonOption { get; set; } = string.Empty;
}
Configuration au démarrage
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Injection de la config
services.Configure<MySettings>(Configuration.GetSection(MySettings.Path));
}
[!TIP]
La méthode d’extensionConfigure<T>(this IServiceCollection services, IConfiguration config)se trouve dansMicrosoft.Extensions.Options.ConfigurationExtensions. Il faut l’ajouter via les packages NuGet.
Injection dans un service
public class MyService
{
private readonly MySettings _settings;
public MyService(IOptions<MySettings> options)
{
_settings = options.Value;
}
}
Les types d’options
En .NET, il existe plusieurs variantes d’IOptions pour gérer la configuration :
-
**IOptions
** Fournit les valeurs de configuration typées. Usage classique : injecté dans le constructeur, accès via `.Value`. -
**IOptionsSnapshot
** Permet d’obtenir la configuration actualisée à chaque requête (scope). Utile pour les applications web où la config peut changer entre les requêtes. -
**IOptionsMonitor
** Permet de surveiller les changements de configuration en temps réel et d’exécuter du code quand la config change. Utile pour les applications qui doivent réagir dynamiquement aux modifications.
Les différentes sources de configuration
En ASP.NET Core et plus généralement en .NET moderne, la configuration peut provenir de plusieurs sources, combinées dans un configuration builder :
- Fichiers JSON :
appsettings.json,appsettings.Development.json, etc. - Variables d’environnement : pratiques pour Docker, Kubernetes, Azure, etc.
- Ligne de commande : utile pour les outils en console.
- User secrets (en développement) : pour stocker des secrets hors du dépôt Git.
- Providers personnalisés : base de données, Vault, API distante…
L’ordre d’enregistrement des providers détermine la priorité : la dernière source ajoutée peut écraser les valeurs des précédentes (ex : une variable d’environnement peut surcharger appsettings.json).
Exemple minimal dans un Program.cs (ASP.NET Core) :
var builder = WebApplication.CreateBuilder(args);
builder.Configuration
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.AddCommandLine(args);
Aller plus loin avec les options typées
L’exemple simple mappe une section plate (CheminOption) vers une classe. On peut de la même façon lier des objets imbriqués ou des listes.
Exemple avec objet imbriqué et liste
{
"MySettings": {
"MonOption": "valeur",
"SousOptions": {
"UrlApi": "https://api.example.com",
"TimeoutSeconds": 30
},
"Serveurs": ["server1", "server2"]
}
}
public class MySettings
{
public const string Path = "MySettings";
public string MonOption { get; set; } = string.Empty;
public SousOptions SousOptions { get; set; } = new();
public List<string> Serveurs { get; set; } = new();
}
public class SousOptions
{
public string UrlApi { get; set; } = string.Empty;
public int TimeoutSeconds { get; set; }
}
Enregistrement dans le conteneur
builder.Services.Configure<MySettings>(
builder.Configuration.GetSection(MySettings.Path));
On peut ensuite injecter IOptions<MySettings>, IOptionsSnapshot<MySettings> ou IOptionsMonitor<MySettings> selon le besoin.
Valider la configuration
Une configuration incorrecte (clé manquante, valeur invalide) ne doit pas être découverte en production au premier appel d’un service. Il est possible de valider les options au démarrage.
Validation via DataAnnotations
using System.ComponentModel.DataAnnotations;
public class MyValidatedSettings
{
public const string Path = "MyValidatedSettings";
[Required]
public string ConnectionString { get; set; } = string.Empty;
[Range(1, 60)]
public int TimeoutSeconds { get; set; }
}
builder.Services
.AddOptions<MyValidatedSettings>()
.Bind(builder.Configuration.GetSection(MyValidatedSettings.Path))
.ValidateDataAnnotations()
.Validate(s => !string.IsNullOrWhiteSpace(s.ConnectionString),
"ConnectionString ne doit pas être vide")
.ValidateOnStart();
Avec ValidateOnStart(), l’application échouera au démarrage si la configuration est invalide, ce qui évite des erreurs plus difficiles à diagnostiquer plus tard.
Recharger la configuration sans redémarrer
Grâce au paramètre reloadOnChange: true sur les fichiers JSON et à IOptionsMonitor<T>, il est possible de mettre à jour la configuration à chaud.
builder.Configuration.AddJsonFile(
"appsettings.json", optional: false, reloadOnChange: true);
builder.Services.Configure<MySettings>(
builder.Configuration.GetSection(MySettings.Path));
public class MonService
{
private readonly IOptionsMonitor<MySettings> _optionsMonitor;
public MonService(IOptionsMonitor<MySettings> optionsMonitor)
{
_optionsMonitor = optionsMonitor;
_optionsMonitor.OnChange(settings =>
{
// Réagir au changement de configuration
Console.WriteLine($"Nouvelle valeur : {settings.MonOption}");
});
}
public void DoWork()
{
var settings = _optionsMonitor.CurrentValue;
// Utiliser la version actuelle de la configuration
}
}
Bonnes pratiques
- Préférer les options typées plutôt que l’accès direct via
IConfigurationpartout. - Centraliser les clés de configuration dans des constantes (
Path) plutôt que de dupliquer les chaînes. - Valider la configuration au démarrage (
ValidateOnStart) pour échouer vite en cas d’erreur. - Utiliser
IOptionsSnapshot<T>dans les applications web si la configuration doit être rechargée à chaque requête. - Utiliser
IOptionsMonitor<T>pour des services longue durée qui doivent réagir aux changements de configuration. - Ne pas exposer directement des valeurs sensibles (secrets) dans les logs ou les exceptions.