Skip to main content 홈 크리에이터 rudironsoni synaxis dotnet-csharp-configuration
dotnet-csharp-configuration Configures Options pattern, user secrets, and feature flags. IOptions<T>, FeatureManagement.
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/rudironsoni/Synaxis --skill dotnet-csharp-configuration명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... name dotnet-csharp-configuration category fundamentals subcategory di-and-services description Configures Options pattern, user secrets, and feature flags. IOptions<T>, FeatureManagement. license MIT targets ["*"] tags ["csharp","dotnet","skill"] version 0.0.1 author dotnet-agent-harness invocable true claudecode {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} codexcli {"short-description":".NET skill guidance for csharp tasks"} opencode {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} copilot {} geminicli {} antigravity {}
dotnet-csharp-configuration
Configuration patterns for .NET applications using Microsoft.Extensions.Configuration and Microsoft.Extensions.Options.
Covers the Options pattern (IOptions<T>, IOptionsMonitor<T>, IOptionsSnapshot<T>), validation, user secrets,
environment-based configuration, and feature flags with Microsoft.FeatureManagement.
Scope
Options pattern (IOptions, IOptionsMonitor, IOptionsSnapshot)
Options validation and ValidateOnStart
User secrets and environment-based configuration
Feature flags with Microsoft.FeatureManagement
Configuration source precedence
Out of scope
DI container mechanics and service lifetimes -- see [skill:dotnet-csharp-dependency-injection]
EditorConfig and analyzer rule configuration -- see [skill:dotnet-editorconfig]
Structured logging pipeline configuration -- see [skill:dotnet-structured-logging]
Cross-references: [skill:dotnet-csharp-dependency-injection] for service registration patterns,
[skill:dotnet-csharp-coding-standards] for naming conventions.
Configuration Sources and Precedence
Default configuration sources in WebApplication.CreateBuilder (last wins):
appsettings.json
appsettings.{Environment}.json
User secrets (Development only)
Environment variables
Command-line arguments
var builder = WebApplication.CreateBuilder(args );
builder.Configuration.AddJsonFile("features.json" , optional: true , reloadOnChange: true );
```csharp
---
## Options Pattern
Bind configuration sections to strongly typed classes and inject them via DI.
### Defining Options Classes
```csharp
public sealed class SmtpOptions
{
public const string SectionName = ;
Host { ; ; } = ;
Port { ; ; } = ;
FromAddress { ; ; } = ;
UseSsl { ; ; } = ;
}
```text
> Options classes use `{ ; ; }` ( ` `) because the configuration binder `PostConfigure` need to mutate
> properties. Use `[Required]` via data annotations mandatory fields instead.
```csharp
builder.Services
.AddOptions<SmtpOptions>()
.BindConfiguration(SmtpOptions.SectionName)
.ValidateDataAnnotations()
.ValidateOnStart();
```text
```json
{
: {
: ,
: ,
: ,
:
}
}
```text
---
| Interface | Lifetime | Reload Behavior | Use Case |
| --------------------- | --------- | --------------------------------- | ------------------------------- |
| `IOptions<T>` | Singleton | Never reloads after startup | Static config, most services |
| `IOptionsSnapshot<T>` | Scoped | Reloads per request/scope | Per-request config ASP.NET |
| `IOptionsMonitor<T>` | Singleton | Live reload + change notification | Singletons, background services |
```csharp
{
SmtpOptions _smtp = options.Value;
{
Task.CompletedTask;
}
}
{
=> monitor.CurrentValue.EnabledFeatures.Contains(feature);
}
{
=> snapshot.Value.MarkupPercent;
}
```text
```csharp
:
{
IDisposable? _changeListener;
CacheOptions _current;
{
_current = monitor.CurrentValue;
_changeListener = monitor.OnChange(updated =>
{
_current = updated;
});
}
=> _changeListener?.Dispose();
}
```text
---
```csharp
System.ComponentModel.DataAnnotations;
{
SectionName = ;
[ ]
Host { ; ; } = ;
[ ]
Port { ; ; } = ;
[ ]
FromAddress { ; ; } = ;
}
builder.Services
.AddOptions<SmtpOptions>()
.BindConfiguration(SmtpOptions.SectionName)
.ValidateDataAnnotations()
.ValidateOnStart();
```text
Use validation logic requires cross-property checks external dependencies.
```csharp
: < >
{
{
failures = List< >();
(options.UseSsl && options.Port == )
{
failures.Add( );
}
( .IsNullOrWhiteSpace(options.Host))
{
failures.Add( );
}
failures.Count >
? ValidateOptionsResult.Fail(failures)
: ValidateOptionsResult.Success;
}
}
builder.Services.AddSingleton<IValidateOptions<SmtpOptions>, SmtpOptionsValidator>();
```text
Always use `.ValidateOnStart()` to surface configuration errors at startup instead of at first resolution. Without it,
invalid config only throws `IOptions<T>.Value` first accessed.
---
Store sensitive values outside source control during development.
```bash
dotnet user-secrets
dotnet user-secrets
dotnet user-secrets
dotnet user-secrets list
dotnet user-secrets clear
```text
User secrets are stored `~/.microsoft/usersecrets/<UserSecretsId>/secrets.json` `appsettings.json`
values Development.
**Key rules:**
- Never use user secrets production -- use environment variables, Azure Key Vault, other vault providers
- User secrets are loaded automatically `ASPNETCORE_ENVIRONMENT=Development`
- For non-web hosts, explicitly : `builder.Configuration.AddUserSecrets<Program>()`
---
```csharp
```csharp
```text
appsettings.json
appsettings.Development.json
appsettings.Staging.json
appsettings.Production.json
```json
```csharp
env = builder.Environment.EnvironmentName;
```csharp
```
{
builder.Services.AddSingleton<IEmailSender, ConsoleEmailSender>();
}
{
builder.Services.AddSingleton<IEmailSender, SmtpEmailSender>();
}
```text
---
`Microsoft.FeatureManagement.AspNetCore` provides structured feature flag support filters, targeting, gradual
rollout.
```bash
dotnet package Microsoft.FeatureManagement.AspNetCore
```bash
```csharp
builder.Services.AddFeatureManagement();
```csharp
```json
{
: {
: ,
: {
: [
{
: ,
: { : }
}
]
},
: {
: [
{
: ,
: {
: {
: [ ],
: [{ : , : }],
:
}
}
}
]
}
}
}
```text
```csharp
{
[ ]
{
( featureManager.IsEnabledAsync( ))
{
Ok( { version = , dashboard = });
}
Ok( { version = , dashboard = });
}
}
```text
```csharp
[ ]
[ ]
{
results = _searchService.SearchAsync(query, ct);
Ok(results);
}
```text
| Filter | Purpose |
| ------------ | -------------------------------------------------------- |
| `Percentage` | Enable N%
{
{
userAgent = accessor.HttpContext?.Request.Headers.UserAgent.ToString() ?? ;
settings = context.Parameters.Get<BrowserFilterSettings>();
Task.FromResult(
settings?.AllowedBrowsers?.Any(b =>
userAgent.Contains(b, StringComparison.OrdinalIgnoreCase)) ?? );
}
}
{
[] AllowedBrowsers { ; ; } = [];
}
builder.Services.AddFeatureManagement()
.AddFeatureFilter<BrowserFeatureFilter>();
```text
---
;
builder.Services
.AddOptions<ApiClientOptions>( )
.BindConfiguration( );
{
{
options = snapshot.Get(name);
HttpClient { BaseAddress = Uri(options.BaseUrl) };
}
}
```text
---
Apply defaults overrides after all configuration sources have been processed.
```csharp
builder.Services.PostConfigure<SmtpOptions>(options =>
{
(options.Port == )
{
options.Port = options.UseSsl ? : ;
}
});
```text
---
```csharp
[ ]
{
options = SmtpOptions
{
Host = ,
FromAddress = ,
Port = ,
UseSsl =
};
validator = SmtpOptionsValidator();
result = validator.Validate( , options);
Assert.True(result.Failed);
Assert.Contains( , result.FailureMessage);
}
[ ]
{
config = ConfigurationBuilder()
.AddInMemoryCollection( Dictionary< , ?>
{
[ ] = ,
[ ] = ,
[ ] = ,
})
.Build();
options = SmtpOptions();
config.GetSection( ).Bind(options);
Assert.Equal( , options.Host);
Assert.Equal( , options.Port);
}
```text
---
**Primary approach:** Use Serena symbol operations efficient code navigation:
**Find definitions**: `serena_find_symbol` instead of text search
**Understand structure**: `serena_get_symbols_overview` organization
**Track references**: `serena_find_referencing_symbols` impact analysis
**Precise edits**: `serena_replace_symbol_body` clean modifications
**When to use Serena vs traditional tools:**
- ✅ **Use Serena**: Navigation, refactoring, dependency analysis, precise edits
- ✅ **Use Read/Grep**: Reading full files, pattern matching, simple text operations
- ✅ **Fallback**: If Serena unavailable, traditional tools work fine
**Example workflow:**
```text
Read: src/Services/OrderService.cs
Grep:
serena_find_symbol:
serena_get_symbols_overview:
```
- [Options pattern .NET](https:
- [Configuration .NET](https:
- [User secrets development](https:
- [Feature management .NET](https:
- [IValidateOptions](https:
- [.NET Framework Design Guidelines](https:
"Smtp"
public
string
get
set
""
public
int
get
set
587
public
string
get
set
""
public
bool
get
set
true
get
set
not
init
and
for
### Registration
### `appsettings.json`
"Smtp"
"Host"
"smtp.example.com"
"Port"
587
"FromAddress"
"noreply@example.com"
"UseSsl"
true
## Options Interfaces
in
### Injection Examples
public sealed class EmailService (IOptions<SmtpOptions> options )
private
readonly
public Task SendAsync (string to, string subject, string body,
CancellationToken ct = default )
return
public sealed class FeatureService (IOptionsMonitor<FeatureOptions> monitor )
public bool IsEnabled (string feature )
public sealed class PricingService (IOptionsSnapshot<PricingOptions> snapshot )
public decimal GetMarkup ()
### Change Notifications with `IOptionsMonitor<T>`
public
sealed
class
CacheService
IDisposable
private
readonly
private
public CacheService (IOptionsMonitor<CacheOptions> monitor )
public void Dispose ()
## Options Validation
### Data Annotations
using
public
sealed
class
SmtpOptions
public
const
string
"Smtp"
Required, MinLength(1)
public
string
get
set
""
Range(1, 65535)
public
int
get
set
587
Required, EmailAddress
public
string
get
set
""
### `IValidateOptions<T>` (Complex Validation)
when
or
public
sealed
class
SmtpOptionsValidator
IValidateOptions
SmtpOptions
public ValidateOptionsResult Validate (string ? name, SmtpOptions options )
var
new
string
if
25
"Port 25 does not support SSL. Use 465 or 587."
if
string
"SMTP host is required."
return
0
### `ValidateOnStart` (Fail Fast)
when
is
## User Secrets (Development)
# Initialize (once per project)
init
# Set values
set
"Smtp:Host"
"smtp.example.com"
set
"ConnectionStrings:Default"
"Server=..."
# List all secrets
# Clear all
in
and
override
in
in
or
when
add
## Environment-Based Configuration
### Environment Variables
### Per-Environment Files
# Base (all environments)
# Overrides for dev
# Overrides for staging
# Overrides for prod
var
### Conditional Service Registration
csharp
if (builder.Environment.IsDevelopment( ))
else
## Feature Flags with Microsoft.FeatureManagement
with
and
### Setup
add
### Configuration
"FeatureManagement"
"NewDashboard"
true
"BetaSearch"
"EnabledFor"
"Name"
"Percentage"
"Parameters"
"Value"
50
"DarkMode"
"EnabledFor"
"Name"
"Targeting"
"Parameters"
"Audience"
"Users"
"alice@example.com"
"Groups"
"Name"
"Beta"
"RolloutPercentage"
100
"DefaultRolloutPercentage"
0
### Usage in Code
public sealed class DashboardController (IFeatureManager featureManager ) : ControllerBase
HttpGet
public async Task<IActionResult> Get (CancellationToken ct = default )
if
await
"NewDashboard"
return
new
"v2"
"new"
return
new
"v1"
"legacy"
### Feature Gate Attribute
FeatureGate("BetaSearch" )
HttpGet("search" )
public async Task<IActionResult> Search (string query, CancellationToken ct = default )
var
await
return
### Feature Filters
for
of requests (random ) |
| `TimeWindow` | Enable between start/end dates |
| `Targeting` | Enable for specific users, groups, or rollout percentage |
| Custom | Implement `IFeatureFilter` for domain-specific logic |
### Custom Feature Filter
```csharp
[FilterAlias ("Browser" )]
public sealed class BrowserFeatureFilter (IHttpContextAccessor accessor ) : IFeatureFilter
public Task<bool > EvaluateAsync (FeatureFilterEvaluationContext context )
var
""
var
return
false
public
sealed
class
BrowserFilterSettings
public
string
get
init
## Named Options
Use named options when you need multiple instances of the same options type (e.g., multiple API clients ).
```csharp
builder.Services
.AddOptions <ApiClientOptions >("GitHub" )
.BindConfiguration ("ApiClients:GitHub" )
"Jira"
"ApiClients:Jira"
public sealed class ApiClientFactory (IOptionsSnapshot<ApiClientOptions> snapshot )
public HttpClient CreateFor (string name )
var
return
new
new
## Post-Configuration
or
if
0
465
25
## Testing Configuration
Fact
public void SmtpOptions_Validates_InvalidPort ()
var
new
"smtp.example.com"
"test@example.com"
25
true
var
new
var
null
"Port 25 does not support SSL"
Fact
public void Configuration_BindsCorrectly ()
var
new
new
string
string
"Smtp:Host"
"smtp.test.com"
"Smtp:Port"
"465"
"Smtp:FromAddress"
"test@test.com"
var
new
"Smtp"
"smtp.test.com"
465
## Code Navigation (Serena MCP)
for
1.
2.
for
file
3.
for
4.
for
# Instead of:
"public void ProcessOrder"
# Use:
"OrderService/ProcessOrder"
"src/Services/OrderService.cs"
## References
in
in
in
in