RE:NODE

აპლიკაციები11 წუთის საკითხავი

ASP.NET Core-ის კონფიგურაცია და საიდუმლოებები, ლეპტოპიდან სერვერამდე

როგორ შრეებად ეწყობა ASP.NET Core-ის კონფიგურაცია: appsettings.json, გარემოები, გარემოს ცვლადები __-ით, user-secrets, options pattern და ვალიდაცია გაშვებისას.

0 მკითხველი

ASP.NET Core კონფიგურაციას წყაროების დასტიდან კითხულობს, და გასაღებს ბოლოს ვინც დააყენებს, ის იმარჯვებს: appsettings.json, შემდეგ appsettings.{Environment}.json, შემდეგ user secrets (მხოლოდ Development-ში), შემდეგ გარემოს ცვლადები, შემდეგ command-line არგუმენტები. შენს ლეპტოპზე საიდუმლოებები user secrets-იდან მოდის. სერვერზე ისინი გარემოს ცვლადებიდან მოდის, ორმაგი ქვედა ტირით ჩაწერილი იქ, სადაც JSON-ში ჩადგმა იყო - ConnectionStrings__Default, Smtp__Password. მიაბი თითოეული სექცია ტიპიზებულ კლასს options pattern-ით, გააკეთე მისი ვალიდაცია აპლიკაციის გაშვებისას, და დაკარგული პაროლი პირველივე წამში გასაგებ შეცდომად იქცევა და არა null reference-ად პირველ მოთხოვნაზე.

ეს არის მთელი მოდელი. პოსტის დანარჩენი ნაწილი ის დეტალებია, რომლებიც წყვეტს, იმუშავებს თუ არა ეს: როგორ ერქმევა გასაღებებს სახელები, რომელი ინტერფეისი კითხულობს ცვლილებებს ხელახლა, რა არის სინამდვილეში user secrets და რა შეცდომები ტოვებს production აპლიკაციას development პარამეტრებზე.

საიდან მოდის კონფიგურაცია#

WebApplication.CreateBuilder(args) ნაგულისხმევ წყაროებს შენთვის აწყობს. რიგით, ყველაზე დაბალი პრიორიტეტიდან ყველაზე მაღლამდე:

რიგიწყაროროდის იტვირთება
1appsettings.jsonყოველთვის, თუ არსებობს
2appsettings.{Environment}.jsonყოველთვის, თუ არსებობს
3User secretsგარემო არის Development
4გარემოს ცვლადებიყოველთვის
5Command-line არგუმენტებიყოველთვის

ყოველი წყარო გასაღებების ბრტყელ ნაკრებს გვაწვდის. როცა ორი წყარო ერთსა და იმავე გასაღებს აყენებს, გვიანდელი იმარჯვებს; გასაღებები, რომლებსაც მხოლოდ ერთი წყარო აყენებს, ხელუხლებლად რჩება. სწორედ ეს ხდის შრეებს სასარგებლოს: appsettings.json ინახავს ყველა პარამეტრს უსაფრთხო ნაგულისხმევით, გარემოს ფაილი რამდენიმეს ცვლის, ხოლო სერვერზე გარემოს ცვლადები იმ რამდენიმეს აწვდის, რომლებიც საიდუმლოა ან კონკრეტული მანქანისთვის სპეციფიკური.

ეს ასევე ნიშნავს, რომ მოძველებული მნიშვნელობა შეიძლება დაიმალოს. სერვერზე თვეების წინ დაყენებული გარემოს ცვლადი გადაფარავს იმას, რასაც დღეს appsettings.Production.json-ში შეცვლი, და ამას არაფერი გეუბნება. როცა პარამეტრი შეცვლაზე უარს ამბობს, ჯერ ზედა შრეებს შეხედე.

გასაღებები, სექციები და ორმაგი ქვედა ტირე#

კონფიგურაცია არის ხე, ორწერტილით შეერთებულ გასაღებებად გაბრტყელებული. ეს JSON:

appsettings.json
{  "ConnectionStrings": {    "Default": "Host=localhost;Database=shop;Username=shop;Password=dev"  },  "Smtp": {    "Host": "smtp.example.com",    "Port": 587,    "From": "shop@example.com"  },  "Cors": {    "Origins": [ "https://example.com", "https://www.example.com" ]  },  "Logging": {    "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" }  }}

ქმნის ისეთ გასაღებებს, როგორიცაა Smtp:Host, Cors:Origins:0 და Logging:LogLevel:Default. მასივები დანომრილ შვილებად იქცევა. გასაღებები რეგისტრს არ არჩევს, ამიტომ smtp:host იმავე მნიშვნელობას კითხულობს.

გარემოს ცვლადების სახელები პორტაბელურად ორწერტილს ვერ შეიცავს, ამიტომ გარემოს provider ნაცვლად ორმაგ ქვედა ტირეს იღებს და თარგმნის:

env
ConnectionStrings__Default=Host=203.0.113.10;Port=5432;Database=shop;Username=shop;Password=...Smtp__Password=...Cors__Origins__0=https://example.comCors__Origins__1=https://www.example.comLogging__LogLevel__Default=Warning

აქ ორი დეტალი აბრკოლებს ხალხს. გარემოს ცვლადებიდან დაყენებული მასივი ელემენტებს ინდექსით ცვლის და არა მთელ მასივს, ამიტომ თუ JSON-ში სამი origin-ია და გარემო აყენებს __0-სა და __1-ს, JSON-იდან მესამე მაინც იქ რჩება. და ერთი ქვედა ტირე უბრალოდ სიმბოლოა: Smtp_Password სხვა გასაღებია, ვიდრე Smtp:Password, და მას ჩუმად უგულებელყოფს ყველაფერი, რაც უკანასკნელს კითხულობს.

მნიშვნელობების პირდაპირ წაკითხვა ერთჯერადი შემთხვევებისთვის მუშაობს:

csharp
var connection = builder.Configuration.GetConnectionString("Default");var smtpHost = builder.Configuration["Smtp:Host"];var port = builder.Configuration.GetValue<int>("Smtp:Port", 587);

GetConnectionString("Default") არის Configuration["ConnectionStrings:Default"]-ის შემოკლება. ყველაფრისთვის, რასაც ერთზე მეტი პარამეტრი აქვს, გამოიყენე ქვემოთ აღწერილი options pattern, ნაცვლად იმისა, რომ სტრიქონული გასაღებები მთელ კოდში მიმოფანტო.

გარემოები და გარემოს მიხედვით ფაილები#

გარემოს სახელი მოდის ASPNETCORE_ENVIRONMENT-იდან, ან DOTNET_ENVIRONMENT-იდან, თუ ის არ არის დაყენებული, და ნაგულისხმევად Production-ია, როცა არცერთი არ არის. შაბლონები Development-ს launchSettings.json-ში აყენებს, რომელსაც dotnet run და Visual Studio იყენებს, მაგრამ არა გამოქვეყნებული აპლიკაცია - და სწორედ ამიტომ მუშაობს სერვერი Production-ად შენი ჩარევის გარეშე.

გარემო სამ რამეს წყვეტს:

  • რომელი appsettings.{Environment}.json ჩაიტვირთება;
  • ჩაიტვირთება თუ არა user secrets (ნაგულისხმევად მხოლოდ Development-ში);
  • რას აბრუნებს app.Environment.IsDevelopment(), რომელსაც შაბლონები developer exception page-ის ჩასართავად და HSTS-ის გამოსართავად იყენებენ.

გამოიყენე Staging მეორე deployment-ისთვის, რომელიც production-ივით უნდა იქცეოდეს, მაგრამ სატესტო მონაცემებს მიუთითებდეს. IsStaging() არსებობს და appsettings.Staging.json ავტომატურად იტვირთება. Staging და production ერთ ანგარიშზე ორივეს გვერდიგვერდ გაშვებას განიხილავს.

რა ეკუთვნის თითოეულ ფაილს: appsettings.json-ში ხვდება ყველა გასაღები, რომელსაც აპლიკაცია კითხულობს, მნიშვნელობებით, რომელთა commit უსაფრთხოა - ჰოსტები, პორტები, feature flag-ები, timeout-ები. appsettings.Development.json-ში ხვდება ლოკალური გადაფარვები, მაგალითად დეტალური ლოგირება. appsettings.Production.json ხშირად საჭირო არ არის; თუ არსებობს, ის production-ის არასაიდუმლო მნიშვნელობებს ინახავს. არცერთი მათგანი არ ინახავს პაროლებს, API გასაღებებს ან connection string-ებს მონაცემებით, რადგან ყველა მათგანი commit-შია.

User secrets დეველოპმენტში#

user secrets დეველოპმენტის მონაცემებს repository-ს გარეთ ინახავს, მათ შენს მომხმარებლის პროფილში ათავსებს და არა პროექტის საქაღალდეში.

bash
$ dotnet user-secrets init$ dotnet user-secrets set "ConnectionStrings:Default" "Host=localhost;Password=dev-only"$ dotnet user-secrets set "Smtp:Password" "app-password-for-testing"$ dotnet user-secrets list

init პროექტის ფაილს UserSecretsId GUID-ს ამატებს. მნიშვნელობები ხვდება უბრალო JSON ფაილში, Windows-ზე %APPDATA%\Microsoft\UserSecrets\<id>\secrets.json-ში, ან Linux-სა და macOS-ზე ~/.microsoft/usersecrets/<id>/secrets.json-ში.

გაიგე, რა არის ეს და რა არა. ფაილი დაშიფრული არ არის; ეს ჩვეულებრივი JSON-ია შენს home დირექტორიაში. მისი ერთადერთი საქმეა, საიდუმლოებები პროექტის ხის გარეთ დატოვოს, რომ შემთხვევით commit-ში არ მოხვდეს. ის მხოლოდ მაშინ იტვირთება, როცა გარემო Development-ია, ამიტომ deployment-ის მექანიზმი არასოდეს არის. გუნდი მისი გავლით არაფერს იზიარებს - თითოეული დეველოპერი საკუთარს აყენებს.

ეს ბოლო პუნქტი .NET-ში პირველი deploy-ის ყველაზე გავრცელებულ ჩავარდნას იწვევს: ლოკალურად ყველაფერი მუშაობს, რადგან connection string user secrets-შია, ხოლო სერვერზე გასაღები უბრალოდ არ არსებობს. აპლიკაცია ეშვება, იღებს მოთხოვნას და გამონაკლისს აგდებს, რადგან connection string null-ია. გაშვებისას ვალიდაცია, ქვემოთ, ამას დაუყოვნებლივ და წაკითხვად ჩავარდნად აქცევს.

საიდუმლოებები სერვერზე#

სერვერზე საიდუმლოებების სტანდარტული ადგილი გარემოს ცვლადებია. ისინი repository-ს გარეთ დგინდება, ჩვეულებრივი კონფიგურაციის სისტემით იკითხება კოდის ცვლილების გარეშე და ყველა ფაილს გადაფარავს.

RE:NODE-ზე მათ სერვერის Startup ჩანართზე აყენებ, და ისინი კონტეინერის შემდეგ გაშვებაზე მოქმედებს - ამიტომ შეცვალე მნიშვნელობა, შემდეგ გადატვირთე. აპლიკაციის გეგმაში ორი database slot შედის, რომლებიც პანელში იქმნება გენერირებული ჰოსტით, მომხმარებლით და პაროლით; დააკოპირე ისინი ConnectionStrings__Default-ში და ნუ ჩადებ commit-ში მოხვედრილ ფაილში. გარემოს ცვლადები და საიდუმლოებები ზოგად წესებს განიხილავს და იმას, რა უნდა გააკეთო იმ დღეს, როცა საიდუმლო მაინც მოხვდება Git-ის ისტორიაში.

რისი გაკეთებაც არ ღირს:

  • ნუ გაუკეთებ commit-ს production `appsettings.Production.json`-ს მონაცემებით, რომ მერე `.gitignore`-ში დაამატო. ის ისტორიაშია. შეცვალე მონაცემი.
  • ნუ ჩაწერ შენს კონფიგურაციას ლოგში. IConfigurationRoot.GetDebugView() სასარგებლო მეთოდია, რომელიც ბეჭდავს ყველა გასაღებს, ყველა მნიშვნელობას და რომელმა provider-მა დააყენა ის - პაროლების ჩათვლით. გამოიყენე ის ლოკალურად; მისი შედეგი production ლოგში არასოდეს ჩაწერო.
  • ნუ გადასცემ საიდუმლოებებს command-line არგუმენტებად. ისინი პროცესების სიაში ჩანს და მათი support ticket-ში ჩასმა ადვილია.

თუ საიდუმლოებების ფაილებიდან წაკითხვა გირჩევნია გარემოს ნაცვლად - თითო ფაილი თითო გასაღებზე, ისე, როგორც კონტეინერის secret mount-ები მუშაობს - Microsoft.Extensions.Configuration.KeyPerFile პაკეტი ამას წყაროდ ამატებს builder.Configuration.AddKeyPerFile("/path/to/secrets", optional: true)-ით. ამ დირექტორიაში Smtp__Password სახელის ფაილი გასაღებ Smtp:Password-ად იქცევა. გარე vault-ებსაც (Azure Key Vault, HashiCorp Vault, AWS Secrets Manager) აქვთ კონფიგურაციის provider-ები; მათ აზრი აქვს, როცა უკვე იყენებ ერთ-ერთს, და არა როგორც პირველ ნაბიჯს ერთი აპლიკაციისთვის.

ერთი პარამეტრი, ყველა შრის გავლით

სასარგებლოა ერთი სექციის კვალის გაყოლა ლეპტოპიდან სერვერამდე. ავიღოთ ზემოთ მოცემული Smtp სექცია.

შენს ლეპტოპზე გარემო Development-ია. Smtp:Host, Smtp:Port და Smtp:From მოდის appsettings.json-იდან. appsettings.Development.json ცვლის Smtp:Host-ს localhost-ზე და Smtp:Port-ს 1025-ზე, ლოკალურ mail catcher-ზე მიმართვით. Smtp:Password მოდის user secrets-იდან. ოთხი გასაღები, სამი წყარო და repository-ში არაფერი საიდუმლო.

სერვერზე გარემო Production-ია. appsettings.Development.json და user secrets საერთოდ არ იტვირთება. Smtp:Host, Smtp:Port და Smtp:From ისევ appsettings.json-იდან მოდის, ამიტომ commit-ში მოხვედრილი ნაგულისხმევები production-ისა უნდა იყოს. Smtp:Password მოდის Smtp__Password გარემოს ცვლადიდან Startup ჩანართზე. თუ მოგვიანებით production-ის ერთი შუადღით სხვა relay-ზე მიმართვა დაგჭირდება, გარემოში Smtp__Host-ის დაყენება ფაილს commit-ის გარეშე გადაფარავს, ხოლო ცვლადის წაშლა commit-ში არსებულ მნიშვნელობას დააბრუნებს.

ჩვევა, რომელიც აქედან გამომდინარეობს: საბაზისო ფაილში commit გაუკეთე production-ისთვის უსაფრთხო ნაგულისხმევებს, დეველოპმენტის მოხერხებულობები Development ფაილში ჩადე, ხოლო გარემო დატოვე საიდუმლოებებისა და შეგნებული, დროებითი გადაფარვებისთვის. თუ აღმოაჩენ, რომ სერვერზე ათეულ არასაიდუმლო ცვლადს აყენებ, ეს მნიშვნელობები ალბათ commit-ში მოხვედრილ ფაილს ეკუთვნის, სადაც ისინი დანარჩენი კოდივით მიმოიხილება და ვერსიონირდება.

options pattern#

სტრიქონების კითხვის ნაცვლად სექცია კლასს მიაბი:

csharp
public sealed class SmtpOptions{    public const string Section = "Smtp";    [Required] public string Host { get; set; } = "";    [Range(1, 65535)] public int Port { get; set; } = 587;    [Required, EmailAddress] public string From { get; set; } = "";    [Required] public string Password { get; set; } = "";}
Program.cs
builder.Services.AddOptions<SmtpOptions>()    .BindConfiguration(SmtpOptions.Section)    .ValidateDataAnnotations()    .ValidateOnStart();

შემდეგ inject გაუკეთე იქ, სადაც საჭიროა. არსებობს სამი ინტერფეისი, და განსხვავება ის არის, როდის იკითხება მნიშვნელობები:

ინტერფეისისიცოცხლის ხანგრძლივობახედავს ცვლილებებს გაშვების შემდეგ
IOptions<T>Singletonარა - იკითხება ერთხელ, პირველ გამოყენებაზე
IOptionsSnapshot<T>Scopedკი - ხელახლა ითვლება ყოველ მოთხოვნაზე
IOptionsMonitor<T>Singletonკი - CurrentValue, პლუს OnChange

ნაგულისხმევად გამოიყენე IOptions<T>. ის ყველაზე იაფი და ყველაზე პროგნოზირებადია: რაც აპლიკაციამ გაშვებისას წაიკითხა, იმას იყენებს restart-მდე. IOptionsSnapshot<T>-ს singleton-ში inject ვერ გაუკეთებ, რადგან ის scoped-ია; ეს შეცდომა გაშვებისას dependency injection-ის შეცდომას იწვევს. IOptionsMonitor<T> იმ singleton-ებისთვისაა, რომლებსაც მართლა სჭირდებათ ცვლილებებზე რეაგირება, მაგალითად ფონური სერვისი, რომლის polling ინტერვალის ცოცხლად რეგულირებაც გინდა.

binder აყენებს public property-ებს setter-ებით, სახელებს რეგისტრის გაურჩევლად ამთხვევს. property, რომელსაც შესაბამისი გასაღები არ აქვს, თავის ნაგულისხმევს ინარჩუნებს, ჩუმად. ამიტომაა ვალიდაცია მნიშვნელოვანი: მის გარეშე გასაღების სახელში შეცდომა ქმნის ნაგულისხმევებით სავსე ობიექტს და არანაირ შეცდომას.

ვალიდაცია გაშვებისას#

ValidateDataAnnotations() კლასზე არსებულ ატრიბუტებს ამოწმებს. ValidateOnStart() შემოწმებას host-ის გაშვებისას უშვებს, ნაცვლად იმ პირველი მომენტისა, როცა რაიმე options-ს ითხოვს. ერთად ისინი დაკარგულ საიდუმლოს აქცევენ ამად, ლოგის პირველივე წამში:

code
Unhandled exception. Microsoft.Extensions.Options.OptionsValidationException:DataAnnotation validation failed for 'SmtpOptions' members: 'Password' with the error:'The Password field is required.'.

ეს არის ქცევა, რომელიც სერვერზე გინდა. პროცესი, რომელიც გაშვებაზე უარს ამბობს წინადადებით, რომელიც დაკარგულ გასაღებს ასახელებს, ორწუთიანი გასწორებაა. ის, რომელიც ეშვება, ტრაფიკს იღებს და პირველ ელფოსტაზე ვარდება, ინციდენტია.

წესებისთვის, რომლებსაც ატრიბუტები ვერ გამოხატავს, დაამატე delegate:

csharp
builder.Services.AddOptions<SmtpOptions>()    .BindConfiguration(SmtpOptions.Section)    .Validate(o => o.Port != 25 || o.Host.EndsWith(".internal"),        "Port 25 is only allowed for the internal relay.")    .ValidateOnStart();

data annotations options კლასის ზედა დონის property-ებს ამოწმებს; ჩადგმული ობიექტები რეკურსიულად არ მოწმდება, თუ მათ აშკარად არ შეამოწმებ. თუ შენს options-ს ჩადგმული სექციები აქვს, თითოეულს საკუთარი options კლასი და საკუთარი ვალიდაცია მიეცი.

პროცესს, რომელიც გაშვებისას გადის, პლატფორმების უმეტესობა გადატვირთავს, და განმეორებით. RE:NODE-ზე საათში სამი მოულოდნელი restart სერვერის გვერდზე გაფრთხილებას აჩენს და ავტომატურად ხსნის ticket-ს, ამიტომ კონფიგურაციის შეცდომა შეუმჩნევლად არ ტრიალებს ციკლში. წაიკითხე ლოგის პირველი ხაზები და არა ბოლო.

ხელახალი ჩატვირთვა redeploy-ის გარეშე#

JSON წყაროები reloadOnChange: true-ით არის რეგისტრირებული, ამიტომ სერვერის დისკზე appsettings.json-ის რედაქტირება მომუშავე აპლიკაციაში კონფიგურაციას ანახლებს. შეამჩნევს თუ არა ამას შენი კოდი, ინტერფეისზეა დამოკიდებული: IOptionsMonitor<T> და IOptionsSnapshot<T> ცვლილებას ხედავს, IOptions<T> - არა, ხოლო მნიშვნელობები, რომლებიც გაშვებისას ველებში დააკოპირე, ცხადია, არა.

ლოგირება ერთადერთი ადგილია, სადაც ეს მართლა სასარგებლოა. ლოგის დონეები monitor-ის გავლით იკითხება, ამიტომ დისკზე ფაილში Logging:LogLevel:Default-ის შეცვლა დეტალურობას restart-ის გარეშე ზრდის ან ამცირებს - მოსახერხებელია production პრობლემის დევნისას. ყველაფერი დანარჩენისთვის კონფიგურაცია პროცესის სიცოცხლის განმავლობაში ფიქსირებულად მიიჩნიე, შეცვალე ის გარემოს გავლით და გადატვირთე. გარემოს ცვლადები ერთხელ იკითხება პროცესის გაშვებისას და არასოდეს იტვირთება ხელახლა. სერვერზე რედაქტირებულ ფაილებს შემდეგი deploy ასევე გადაწერს, თუ ისინი repository-ში ტრეკინგდება, რაც კარგი მიზეზია, რომ სერვერზე ტრეკინგ ფაილები ხელით საერთოდ არ შეცვალო. ლოგები, რომლებიც ღირს შენახვად დონეების არჩევაზე მეტს მოგიყვება.

გავრცელებული შეცდომები#

პარამეტრი არ იცვლება. მას ზედა შრე აყენებს. ჯერ გარემოს ცვლადები შეამოწმე, შემდეგ command-line არგუმენტები.

ლოკალურად მუშაობს, სერვერზე კი null-ია. მნიშვნელობა user secrets-შია, რომელიც მხოლოდ Development-ში იტვირთება. დააყენე ის გარემოს ცვლადად სერვერზე.

სერვერი development პარამეტრებით მუშაობს. ASPNETCORE_ENVIRONMENT=Development სერვერის გარემოში რომელიღაც სახელმძღვანელოდან დააკოპირეს. წაშალე; ნაგულისხმევი Production-ია.

გარემოს ცვლადი იგნორირდება. ორის ნაცვლად ერთი ქვედა ტირე, შეცდომა სექციის სახელში, ან აპლიკაცია ცვლილების შემდეგ არ გადაიტვირთა.

options-ში ყველაფერი ნაგულისხმევია. BindConfiguration-ისთვის გადაცემული სექციის სახელი JSON-ს არ ემთხვევა, ან property-ებს setter-ები არ აქვს. ვალიდაცია ამას დაიჭერდა.

"Cannot consume scoped service IOptionsSnapshot from singleton". singleton-ებში გამოიყენე IOptionsMonitor<T>.

რიცხვი ან boolean არასწორია. კონფიგურაციის ყოველი მნიშვნელობა სტრიქონია, სანამ არ მიება. "Port": "587" და "Port": 587 ერთნაირად ებმება, მაგრამ boolean, დაწერილი როგორც yes, ან პორტი, დაწერილი როგორც 587/tcp, კონვერტაციას ვერ გადის - და შეცდომა გასაღებს ასახელებს, ამიტომ წაიკითხე.

საიდუმლო მაინც ლოგშია. რაღაცამ მთელი options ობიექტი ჩაწერა ლოგში, ან გამონაკლისის შეტყობინებამ connection string შეიცვა. გადაფარე ToString() options კლასებზე, რომლებიც საიდუმლოებებს ინახავს, და შეამოწმე, რას აკეთებს შენი ლოგირების ბიბლიოთეკა სტრუქტურირებულ property-ებად გადაცემულ ობიექტებთან.

FAQ#

უსაფრთხოა საიდუმლოებების გარემოს ცვლადებში შენახვა?

საკმარისად უსაფრთხოა აპლიკაციების უმეტესობისთვის და გაცილებით უსაფრთხო, ვიდრე commit-ში მოხვედრილი ფაილები. ნებისმიერს, ვისაც პროცესის გარემოს ან პანელის Startup ჩანართის წაკითხვა შეუძლია, მათი წაკითხვაც შეუძლია, ამიტომ შეზღუდე, ვის აქვს ეს წვდომა - subuser-ები და მინიმალური პრივილეგიები პანელის ნებართვების დაყოფას განიხილავს.

უნდა მოხვდეს appsettings.Production.json commit-ში?

კი, თუ ის მხოლოდ არასაიდუმლო მნიშვნელობებს ინახავს. თუ მას საიდუმლო სჭირდება, ეს საიდუმლო ნაცვლად გარემოს ცვლადს ეკუთვნის და ფაილი მას საერთოდ არ უნდა შეიცავდეს.

საჭიროა სერვერზე ASPNETCORE_ENVIRONMENT-ის დაყენება?

არა. ნაგულისხმევი Production-ია, რაც სწორია. დააყენე ის მხოლოდ შეგნებულად განსხვავებული გარემოსთვის, მაგალითად Staging-ისთვის.

როგორ დავაყენო წერტილ-მძიმის შემცველი connection string გარემოს ცვლადში?

დააყენე ისე, როგორც არის; წერტილ-მძიმეები მნიშვნელობის ნაწილია და Startup ჩანართზე escape-ს არ საჭიროებს. მის გარშემო ბრჭყალები მხოლოდ shell-ს დასჭირდებოდა. .NET PostgreSQL-ით, MySQL-ით თუ SQL Server-ით თითოეული provider-ისთვის მომუშავე connection string-ს აჩვენებს.

შემიძლია კონფიგურაცია აპლიკაციის გადატვირთვის გარეშე შევცვალო?

IOptionsMonitor<T>-ით წაკითხული მნიშვნელობებისთვის ან ლოგის დონეებისთვის დისკზე JSON ფაილის რედაქტირება მუშაობს. გარემოს ცვლადებს ყოველთვის restart სჭირდება. პროგნოზირებადი აპლიკაციისთვის restart ამჯობინე.


კომენტარები

სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.

0/2000