Mon ami et collègue, Paul Ballard, a partagé le récent article d'Andrew Lock sur un problème lié à une erreur de "chaîne de connexion manquante" dans une nouvelle application ASP.NET Core s'exécutant dans Docker. Andrew, l'auteur du nouveau livre ASP.NET Core in Action nous a gracieusement autorisé à republier son article . Dans cet article, non seulement il couvre l’arrière-plan de base des environnements dans ASP.NET Core, mais il explique également comment vous utiliseriez une configuration spécifique à l’environnement. Il décrit le bogue et fournit sa solution.
Andrew Lock, développeur à plein temps, travaille principalement au développement ASP.NET à pile complète à Devon, au Royaume-Uni.
J'espère que vous apprécierez!
Chargement de la configuration spécifique à l’environnement ASP.NET Core
Par Andrew Lock
Je venais de mettre au point une nouvelle application ASP.NET Core exécutée dans Docker, et j’observais un comportement très étrange. L'application pourrait démarrer sans aucun problème lors de l'exécution locale sur mon ordinateur Windows. Mais lorsque je le poussais sur le serveur de génération, l'application échouait immédiatement, invoquant une "chaîne de connexion manquante" ou quelque chose de similaire. J'ai passé une bonne demi-heure à essayer de résoudre le problème, alors cet article est juste au cas où quelqu'un d'autre rencontrerait le même problème!
Dans cet article, je vais couvrir le contexte de base des environnements dans ASP.NET Core et décrire comment vous utiliseriez généralement une configuration spécifique à un environnement. Enfin, je décrirai le bogue que j’ai rencontré et la raison pour laquelle il s’agissait d’un problème.
dr;
IHostingEnvironment
ignore le cas de l’environnement actuel lorsque vous utilisez leIsDevelopment () Cependant, si vous utilisez des fichiers de configuration spécifiques à l'environnement, par exemple
appsettings.Development.json
vous devez faire attention au cas. Si vous définissez l'environnement surdevelopment
au lieu deDevelopment
vos fichiers de configuration ne se chargeront pas sur un système d'exploitation sensible à la casse tel que Linux.
ASP.NET Core Environments
ASP. NET Core a le concept d'environnements qui représente les différents emplacements où votre code peut s'exécuter. Vous pouvez déterminer l'environnement actuel au moment de l'exécution et utiliser cette valeur pour modifier le comportement de votre application. Par exemple, dans Startup.Configure ()
il est courant de configurer votre pipeline d'intergiciels différemment si vous exécutez Development
par opposition à Production
:
. ] public void Configure (application IApplicationBuilder, env. IHostingEnvironment)
{
// ajouté uniquement lors de l'exécution en développement
if (env.IsDevelopment ())
{
app.UseDeveloperExceptionPage ();
}
// ajouté uniquement lors de l'exécution en production
if (env.IsProduction ())
{
app.UseExceptionHandler ("/ Error");
}
app.UseStaticFiles ();
app.UseMvc ();
}
Vous pouvez utiliser IHostingEnvironment
n'importe où dans votre application où vous souhaitez vérifier l'environnement actuel et vous comporter de manière différente en fonction de la valeur.
ASP.NET Core connaît par défaut trois environnements, et fournit des méthodes d'extension pour travailler avec elles:
Développement
: identifié à l'aide deIHostingEnvironment.IsDevelopment ()
Staging
: identifié à l'aide deIHostingEnvironment.IsStaging ()
Production
.
: identifié avecIHostingEnvironment.IsProduction ()
Vous pouvez également visualiser la valeur de l'environnement actuel en lisant IHostingEnvironment.EnvironmentName
directement, mais il est vivement recommandé d'utiliser l'une des méthodes d'extension. . Les méthodes d'extension prennent soin de faire une comparaison insensible à la casse entre le EnvironmentName
et la chaîne attendue (c'est-à-dire Development
).
code avec des vérifications impératives de l'environnement, une approche généralement plus propre consiste à utiliser une configuration spécifique à l'environnement, que je décrirai plus tard.
Primaire de configuration pour ASP.NET Core
Le système de configuration dans ASP.NET Core est construit. de couches de valeurs de configuration, compilées à partir de sources multiples. Vous pouvez charger des valeurs à partir de fichiers JSON fichiers XML variables d'environnement ou vous pouvez créer un fournisseur personnalisé pour charger des valeurs à partir de à peu près n'importe où .
Vous pouvez créer un objet de configuration en ajoutant des fournisseurs à un objet IConfigurationBuilder. Cela se produit généralement dans Program.cs
à l'aide de la méthode IWebHostBuilder.ConfigureAppConfiguration
. WebHost.CreateDefaultBuilder ()
appelle cette méthode en arrière-plan dans une application ASP.NET Core 2.x typique. Chaque fournisseur ajouté à IConfigurationBuilder
ajoute une autre couche de configuration. Par exemple, le code suivant ajoute un fichier JSON ( appsettings.json
) et des variables d'environnement à l'objet de configuration final:
IHostingEnvironment env;
var builder = new ConfigurationBuilder ()
.SetBasePath (env.ContentRootPath) // le chemin depuis lequel le fichier JSON doit être chargé
.AddEnvironmentVariables ();
L’ordre des fournisseurs de configuration est important ici; Si une variable d'environnement porte le même nom qu'un paramètre du fichier JSON, le paramètre JSON sera écrasé. La configuration finale sera une vue "aplatie" des paramètres de toutes les sources de configuration.
Je pense que l'aplatissement des fournisseurs de configuration est similaire à l'aplatissement des calques dans une image Photoshop. chaque couche remplace les valeurs des couches précédentes, sauf si elle est transparente (c'est-à-dire si la couche n'a pas de valeur).
Par exemple, imaginez que vous disposiez du fichier de configuration suivant: appsettings.json
:
{
"Enregistrement": {
"LogLevel": {
"Par défaut": "Debug",
"Système": "Information",
"Microsoft": "Information"
}
}
}
Cela générerait seul les paramètres suivants:
"Logging: LogLevel: Default" = "Debug";
"Logging: LogLevel: System" = "Informations";
"Logging: LogLevel: Microsoft" = "Information";
Toutefois, si vous aviez également une variable d'environnement:
Logging__LogLevel__Default = Warning
et l'a chargé après votre fichier JSON, le fichier final. la configuration serait la suivante (notez le changement de valeur pour le premier paramètre):
"Logging: LogLevel: Default" = "Warning";
"Logging: LogLevel: System" = "Informations";
"Logging: LogLevel: Microsoft" = "Informations";
Configuration spécifique à l'environnement
"L'aplatissement" des fournisseurs de configuration vous permet d'avoir une configuration spécifique à l'environnement. Prenons le cas habituel où vous souhaitez utiliser un paramètre différent dans le développement local par rapport à la production. Vous pouvez y parvenir de différentes manières, par exemple:
- Écraser les valeurs par défaut par ex. définissez uniquement une variable d'environnement pour le paramètre dans Production.
- Utilisez des paramètres de fournisseur de configuration différents par ex. Chargez les paramètres depuis Azure Key Vault en production et les secrets d'utilisateur pour le développement local.
- Chargez des fournisseurs de configuration supplémentaires p. Ex. charger un fichier JSON spécifique à l'environnement supplémentaire
Ces deux derniers points sont essentiellement la même chose, mais je voulais les appeler comme différents, car ils sont généralement utilisés pour deux choses légèrement différentes, les secrets par rapport aux paramètres.
Les secrets tels que les clés d'API et les chaînes de connexion, ne doivent pas être stockés dans votre référentiel. Pour le développement local, les valeurs sensibles doivent être stockées dans User Secrets . En production, les secrets doivent être récupérés auprès d'un fournisseur tel que Azure Key Vault .
En revanche, les paramètres ne sont pas des valeurs sensibles, ils représentent simplement un élément que vous pouvez configurer différemment. entre les environnements. Par exemple, vous souhaitez peut-être utiliser davantage de mémoire cache en production ou écrire des fichiers journaux à différents emplacements.
Dans le cadre d’une nouvelle application .NET Core que je construisais, j’exécutais une test "sur le conteneur Docker produit, comme décrit dans mon dernier message . Cela implique d'exécuter le conteneur Docker sur le serveur de génération et de vérifier que le conteneur démarre correctement. L'idée est de vérifier que la configuration initiale au démarrage de l'application est correcte. Une de ces vérifications est que toute validation des paramètres fortement typés fonctionne correctement.
J'ai essayé de déboguer localement, d'ajouter et de supprimer le fichier et de modifier la valeur du paramètre. J'essayais de confirmer que le fichier était bien chargé correctement et que les paramètres ne venaient pas ailleurs lors de l'exécution locale. Tout était correct.
J'ai vérifié qu'il n'y avait pas de variables d'environnement inattendues remplaçant la valeur lorsque l'application était exécutée dans Docker pour le test de détection de fumée.
J'ai jeté un œil à l'intérieur du conteneur Docker et vérifié que le fichier appsettings.Development.json
existait et se trouvait au bon endroit. Tout semblait bien se passer.
Enfin, j'ai vérifié que je courais dans l'environnement auquel je m'attendais - Développement. En regardant les journaux du conteneur lorsque le test de fumée a été exécuté, j'ai pu constater que l'environnement d'hébergement était correct selon l'application:
Le script de test de fumée que j'utilisais est très similaire au script de mon dernier message . La commande que j'utilisais pour exécuter ma nouvelle application pour le test de fumée est présentée ci-dessous:
Soyez toujours cohérent avec vos noms d'environnement. Le cas peut ne pas avoir d’importance si vous utilisez Windows, mais ce sera certainement le cas si votre application est exécutée sous Linux. Le framework ASP.NET Core lui-même veille à ignorer la casse lors de la détermination de l'environnement actuel, mais vous ne pouvez pas faire confiance au système d'exploitation sous-jacent pour faire de même!
Note de la rédaction: merci encore à Andrew Lock de nous avoir permis de partager cette information. corrigez-vous en republiant cet article.
Les commentaires sont désactivés en mode Prévisualisation.
Source link