TB
← Tüm yazılar

Configuration ve options pattern

ASP.NET Core yapılandırma kaynaklari, IOptions ailesi ve tip-güvenli konfigurasyon yönetimi ile ortam bazli ayarlarin güvenli kullanımı.

ASP.NET Core'un configuration sistemi, uygulama ayarlarini kod disina tasiyarak ayni binary'nin farklı ortamlarda calismasini sağlar. JSON dosyalari, ortam degiskenleri, Azure Key Vault, user secrets ve command-line argumanlari tek bir birlesik anahtar-deger modelinde toplanir. Bu model uzerine oturan options pattern ise ayarlari strongly-typed siniflara baglayarak derleme zamaninda yapı güvenliği kazandirir.

Configuration provider zinciri

WebApplication.CreateBuilder cagrildiginda varsayilan provider'lar sirayla yuklenir. Sonraki kaynak, oncekini ayni anahtar icin override edebilir. Tipik öncelik (dusukten yuksege):

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. User secrets (Development)
  4. Ortam degiskenleri (cift alt cizgi veya cift iki nokta ile ic ice anahtar)
  5. Command-line

Ortam degiskeni ConnectionStrings__Default veya ConnectionStrings:Default seklinde ConnectionStrings:Default anahtarini override eder. Container ve Kubernetes deployment'larinda bu mekanizma standarttir.

IOptions, IOptionsSnapshot, IOptionsMonitor

Uc arayüz farklı yaşam dongusu ve yeniden yükleme davranisi sunar:

  • IOptions<T>: Singleton. Uygulama baslangicindaki degerleri dondurur; degismez.
  • IOptionsSnapshot<T>: Scoped. Her request'te güncel snapshot; appsettings reload destekler.
  • IOptionsMonitor<T>: Singleton ama OnChange ile canli güncelleme dinlenebilir.
public class EmailOptions
{
    public const string SectionName = "Email";
    public string SmtpHost { get; set; } = "";
    public int Port { get; set; } = 587;
    public bool UseTls { get; set; } = true;
}

builder.Services.Configure<EmailOptions>(
    builder.Configuration.GetSection(EmailOptions.SectionName));

Controller veya serviste IOptions<EmailOptions> enjekte edilir; .Value ile erisilir.

Data annotations ve ValidateOnStart

Options sinifina validation attribute eklemek erken hata yakalamayi sağlar:

public class DatabaseOptions
{
    [Required, MinLength(10)]
    public string ConnectionString { get; set; } = "";

    [Range(1, 300)]
    public int CommandTimeoutSeconds { get; set; } = 30;
}

builder.Services.AddOptions<DatabaseOptions>()
    .Bind(configuration.GetSection("Database"))
    .ValidateDataAnnotations()
    .ValidateOnStart();

ValidateOnStart ile uygulama ayaga kalkmadan once eksik veya gecersiz konfigurasyon tespit edilir; uretimde gec saatlerde patlayan null reference'lar onlenir.

PostConfigure ve named options

Birden fazla ayni tip options gerektiginde IOptionsFactory ve isimli options kullanılır:

builder.Services.Configure<CacheOptions>("Redis", config => { ... });
builder.Services.Configure<CacheOptions>("Memory", config => { ... });

public class DualCacheService
{
    private readonly CacheOptions _redis;
    private readonly CacheOptions _memory;

    public DualCacheService(
        IOptionsSnapshot<CacheOptions> options)
    {
        _redis = options.Get("Redis");
        _memory = options.Get("Memory");
    }
}

IPostConfigureOptions<T> ile kayıt sonrasi tüm options ornekleri uzerinde merkezi düzenleme yapilabilir; örneğin varsayilan timeout'lari ortam bazli ayarlamak.

Secret yönetimi

Hassas degerler appsettings.json'da duz metin tutulmamali. Development'ta user secrets, uretimde Key Vault veya managed identity entegrasyonu kullanın:

builder.Configuration.AddAzureKeyVault(
    new Uri(vaultUri),
    new DefaultAzureCredential());

Options sinifinda secret alanlari loglanmamali; ToString override'inda maskeleme dusunun.

Options pattern ve HttpClient factory

Named HttpClient ile options birlestirmek yaygın bir kalıptir:

builder.Services.Configure<PaymentGatewayOptions>(configuration.GetSection("PaymentGateway"));

builder.Services.AddHttpClient<IPaymentClient, PaymentClient>((sp, client) =>
{
    var opts = sp.GetRequiredService<IOptions<PaymentGatewayOptions>>().Value;
    client.BaseAddress = new Uri(opts.BaseUrl);
    client.Timeout = TimeSpan.FromSeconds(opts.TimeoutSeconds);
});

Boylece URL ve timeout tek konfigurasyon noktasindan gelir; test ortaminda mock server adresi kolayca değiştirilir.

Feature flags ve options

Basit feature toggle'lar boolean options ile modellenir. Daha gelismis senaryolarda Microsoft.FeatureManagement kutuphanesi IConfiguration uzerinden okunur; yine de temel pattern aynidir: davranisi kod icinde sabitlemek yerine yapilandirmaya tasimak.

Test ortaminda configuration

Entegrasyon testlerinde WebApplicationFactory ile configuration override edilir:

builder.ConfigureAppConfiguration((context, config) =>
{
    config.AddInMemoryCollection(new Dictionary<string, string?>
    {
        ["Database:ConnectionString"] = testContainer.GetConnectionString()
    });
});

Birim testlerde Options.Create(new EmailOptions { ... }) ile dogrudan IOptions<T> mock'lanir.

Anti-pattern'ler

  • IConfiguration'in her yere enjekte edilmesi: Magic string anahtarlari cogalir; options sinifina toplayin.
  • Runtime'da IConfiguration'dan sürekli okuma: Performans ve test zorlug; snapshot veya monitor kullanın.
  • Options icinde servis cozme: Options POCO olmali; is mantigi tasimamali.
  • Reload'un IOptions ile beklenmesi: Singleton olduğu icin guncellenmez; snapshot/monitor secin.

Özet

Configuration sistemi ASP.NET Core uygulamalarinin ortam bagimsizligini sağlar. Options pattern bu degerleri tip-güvenli, test edilebilir ve validate edilebilir hale getirir. IOptions ailesinden doğru arayüzü secmek, secret'lari güvenli kaynaklardan okumak ve ValidateOnStart ile erken dogrulama yapmak; operasyonel guvenilirligi ve geliştirici deneyimini birlikte iyilestirir.

Configuration binding derinligi

ICollection ve dictionary binding ic ice JSON yapisini otomatik map eder. Nullable reference type ile birlikte eksik bolumler null veya default deger alir; ValidateDataAnnotations bunu yakalar. Complex type listelerinde index tabanli anahtarlar (Servers:0:Host) ortam degiskenlerinde kullanılır.

Custom IConfigureOptions

Birden fazla kaynaktan gelen ayarlari birlestirmek icin IConfigureOptions<T> implementasyonu yazilir. Örneğin varsayilan EmailOptions uzerine ortam adina gore SMTP port override etmek merkezi bir configure sinifinda toplanabilir.

Hot reload ve geliştirici deneyimi

dotnet watch ile appsettings degisikligi IOptionsMonitor uzerinden algilanabilir. Feature toggle'lari reload edilebilir yapmak deployment beklemeden A/B test ve acil kapatma (kill switch) imkani verir; ancak güvenlik ile ilgili ayarlarin hot reload ile degismesi audit gerektirir.

Advanced scenarios

Multi-tenant uygulamalarda tenant bazli configuration provider yazilabilir; IConfigurationSource implementasyonu tenant id'ye gore ayri JSON veya veritabanı satiri okur. Options monitor ile tenant degisimi runtime'da yansitilabilir.

Configuration key'leri documentation'da tutulmali; eksik anahtar production incident'lerinin önemli bir kismindan biridir.

Environment ve IHostEnvironment

IHostEnvironment.EnvironmentName Development, Staging, Production gibi degerler alir. IsDevelopment() extension'i user secrets ve detayli hata sayfalarini kosullu acar. Ortam adi DOTNET_ENVIRONMENT veya ASPNETCORE_ENVIRONMENT ile set edilir; container orchestrator'da ConfigMap veya env block ile tanimlanir.

Options validation pipeline

ValidateOnStart dışında IValidateOptions<T> ile capraz alan dogrulama yapilir. Örneğin RetryCount sifir ise RetryDelay yok sayilmali gibi kurallar annotation ile ifade edilemez. Startup'ta fail-fast davranisi deployment pipeline'da erken geri bildirim sağlar.

Configuration ve logging

Serilog veya built-in logging de configuration'dan beslenir. Logging:LogLevel:Default appsettings'ten okunur. Options pattern ile logging ayarlari da strongly-typed sinifa baglanabilir; test ortaminda MinimumLevel override edilir.

Azure App Configuration entegrasyonu

Merkezi konfigurasyon servisi feature flag, label (ortam) ve refresh interval sunar. AddAzureAppConfiguration ile baglanildiginda IOptionsMonitor otomatik refresh alir. Key prefix ile uygulama bazli ayirim yapilir; shared key'ler dikkatle yonetilmelidir.

ASP.NET Core ve modern C# ekosisteminde katmanli tasarım, test edilebilirlik ve operasyonel gozlemlenebilirlik birlikte dusunuldugunde uzun omurlu yazılım urunleri ortaya cikar.