Nouveautés de la configuration ASP.Net Core

Historiquement, pour paramétrer une application ASP .NET, il fallait passer par le fichier “web.config“. Puis un beau jour, Microsoft eut la merveilleuse idée de repartir from scratch pour la création du framework ASP .NET Core ! Dorénavant, nous sommes libres d’utiliser le format que l’on souhaite et il nous est également possible de combiner différentes sources de configurations afin de parvenir à nos fins.
Avoir le choix c’est bien, mais savoir quelle source de configuration est la plus adaptée dans notre situation, ou encore savoir comment orchestrer ces différentes sources, c’est mieux ! Nous allons donc répondre à ces deux questions.
NB : il ne sera pas question ici de savoir comment traiter la configuration dans l’application mais de savoir comment on spécifie et override celle-ci. Si vous êtes déçu de cela, je vous invite à aller lire cette doc qui le fera bien mieux que je ne pourrais le faire 🙂
La configuration de C à N
Tout d’abord, qu’est-ce que la configuration et à quoi sert-elle ?
Cela consiste à configurer les différents paramètres d’une application qui peuvent être modifiés afin d’en altérer son comportement pour qu’elle puisse s’adapter à ce que l’on attend d’elle.
Ainsi, nous allons distinguer deux catégories de configuration :
- celle qui intervient durant la création (compilation) de l’application,
- celle qui intervient lors de l’exécution.
La première est statique, la seconde dynamique. L’intérêt n’est donc pas le même, et pour modifier la première, il faudra effectuer plus de manipulations que pour la seconde.
Mais du coup, comment déterminer si ma fonctionnalité doit être configurée dynamiquement ou pas ? Eh bien, il n’y a pas de réponse générique à cette question, tout dépendra du besoin. Cependant, la tendance est actuellement à la modularité et il est donc conseillé de rendre nos briques les plus malléables possible afin de simplifier leur réutilisation.
La configuration dans ASP .NET Core 2.X
Bien que nous soyons libres d’utiliser la source de configuration que l’on souhaite, Microsoft a pris le parti de la modularité et par défaut, seuls les fichiers appsettings.json, les variables d’environnement et la ligne de commande sont pris en charge. Si l’on veut utiliser un fichier ini par exemple, il faudra installer le NuGet correspondant.
Ensuite, pour comprendre comment le Framework traite nos sources de configuration, il faut regarder du côté du fichier Program.cs. C’est dans celui-ci que le chargement de l’application se produit :
public static void Main(string[] args) { WebHost.CreateDefaultBuilder(args) .UseStartup() .Build() .Run(); }
Comme on peut le constater ci-dessus, nous faisons appel à la méthode CreateDefaultBuilder qui simplifie la création de l’application, mais aussi sa configuration. Donc pour obtenir les détails on va voir sur GitHub et on observe donc le fonctionnement suivant :
- on charge la configuration du fichier appsettings.json s’il existe,
- puis on charge celle du fichier appsettings.environment.json s’il existe,
- puis on y rajoute les variables d’environnement,
- et enfin, on termine en ajoutant les arguments fournis en ligne de commande.
On peut ensuite en déduire que si un paramètre est défini dans le appsettings.json et en tant que variable d’environnement, c’est cette dernière qui va l’emporter et sera donc appliquée. A contrario, si un paramètre n’est spécifié dans aucune des configurations, alors il aura la valeur par défaut telle qu’il se l’aura défini.
Petite recommandation
N’hésitez pas à définir tous vos paramètres dans le appsettings.json même s’il sont trop critiques pour être mis ici, mettez-les juste en commentaire avec une valeur vide. Cela vous permettra par la suite de savoir en un coup d’œil tous les paramètres disponibles pour votre application.
Nota Bene : variable d’environnement et underscore
La question suivante revient souvent lorsque l’on essaye de modifier la configuration d’une application ASP .NET Core : “Je voudrais overrider ma chaîne de connexions à partir d’une variable d’environnement et j’ai essayé “CONNECTIONSTRINGS_MYAPPDATABASE” mais cela ne marche pas, saurais-tu pourquoi ?”
Si on se base sur le fichier appsettings suivant, on constate que les connexions strings sont définies dans la section ConnectionStrings. De plus, pour pouvoir overrider, un paramètre on doit écrire le chemin d’accès complet de ce paramètre depuis la racine soit :
- ConnectionsStrings > MyAppDatabase
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
},
"ConnectionStrings": {
"MyAppDatabase": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MyApp;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
}
}
Et donc en consultant la documentation, il est spécifié que le symbole séparateur dans le cas des variables d’environnement est soit le deux point, soit un double underscore. Donc la réponse à cette question est simple, il faut doubler le underscore, ce qui nous donnera :
- CONNECTIONSTRINGS__MYAPPDATABASE
Mais alors Jamy, pourquoi quand je veux modifier l’environnement de mon application (Production/Staging/Development) je spécifie “ASPNETCORE_ENVIRONMENT” et non pas “ASPNETCORE__ENVIRONMENT” ? Ce n’est pas logique tout ça !
Eh bien pour répondre à cette question, il faut se pencher sur le code source du Framework et plus précisément sur la librairie Microsoft.AspNetCore.Hosting. On y trouve plus particulièrement cette ligne-ci :
_config = new ConfigurationBuilder() .AddEnvironmentVariables(prefix: "ASPNETCORE_") .Build();
Par ici pour voir le fichier en entier : https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs#L46
Cette ligne nous explique donc que pour la partie hosting de l’application, le Framework vient récupérer de manière indépendante du système d’injection de dépendance, les variables d’environnement du système où il s’exécute ! De plus, il vient récupérer toutes les variables qui commencent par “ASPNETCORE_”, leur enlève ce préfixe et les traite. Pour lui, ces paramètres ne sont pas regroupés sous une section “ASPNETCORE” mais sont écrits directement à la racine. Et donc le préfixe n’est utilisé que pour éviter d’éventuels conflits de nommage.
Cette ligne de code nous permet aussi de comprendre pourquoi. Si on essaye de définir la variable “ASPNETCORE_ENVIRONMENT” depuis le appsettings, ça ne sera pas pris en compte puisqu’il ne se réfère pas au système de configuration standard !
Conclusion
Pour résumer, ce qu’il faut retenir : les variables préfixées par “ASPNETCORE_” ne représentent pas une structure hiérarchique comme pour les connexions strings et il ne faut donc pas prendre exemple sur elles et utiliser un double underscore.
Et pour aller plus loin, vous pouvez voir la liste des variables spécifiques d’ASP.Net Core commençant par “ASPNETCORE_” sur cette page-ci : https://docs.microsoft.com/en-us/aspnet/core/fundamentals/hosting?tabs=aspnetcore2x