Configuration Guide: ConnectSoft API Library Template¶
The ConnectSoft API Library Template leverages the robust .NET Options pattern for managing configuration settings. This approach provides strongly-typed access to configuration values, integrates seamlessly with Dependency Injection (DI), and supports powerful validation mechanisms.
The Options Pattern Overview¶
The Options pattern provides a way to access configuration values as strongly-typed objects. This offers several benefits:
- Strongly-Typed Access: Eliminates magic strings and provides compile-time safety
- Validation: Allows for validation of configuration values, ensuring they meet specific criteria
- Isolation: Configuration for a specific component is encapsulated in its own options class
- DI Integration: Options classes are easily injected into services using
IOptions<T>,IOptionsSnapshot<T>, orIOptionsMonitor<T>
Service Options¶
The main service options class ({ServiceName}ServiceOptions) contains all configuration for the API service.
Base Configuration¶
Complete Service Options Structure¶
public sealed class MyServiceOptions
{
[Required]
[DataType(DataType.Url)]
required public string BaseUrl { get; set; }
[Required]
[Range(typeof(TimeSpan), "00:00:01", "00:05:00")]
required public TimeSpan DefaultTimeout { get; set; }
[Required]
[ValidateObjectMembers]
required public WebProxyOptions WebProxy { get; set; }
[Required]
required public bool EnableHttpStandardResilience { get; set; }
[Required]
[ValidateObjectMembers]
required public HttpStandardResilienceOptions HttpStandardResilience { get; set; }
[Required]
required public bool EnableHttpStandardHedgingResilience { get; set; }
[Required]
[ValidateObjectMembers]
required public HttpStandardHedgingResilienceOptions HttpStandardHedgingResilience { get; set; }
[Required]
required public bool EnableChaosInjection { get; set; }
[Required]
[ValidateObjectMembers]
required public ChaosInjectionOptions ChaosInjection { get; set; }
// Authentication options (conditional based on AuthenticationType)
}
Authentication Options¶
API Key Authentication¶
{
"MyService": {
"ApiKeyAuthentication": {
"ApiKey": "your-api-key-here",
"HeaderName": "X-API-Key"
}
}
}
Basic Authentication¶
{
"MyService": {
"BasicAuthentication": {
"Username": "your-username",
"Password": "your-password"
}
}
}
OAuth2 Authentication¶
{
"MyService": {
"OAuth2Authentication": {
"ClientName": "MyService",
"OAuthHttpHandler": {
"OAuth2Options": {
"TokenEndpoint": "https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token",
"DefaultTimeout": "00:00:10",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret",
"GrantType": "ClientCredentials",
"CredentialsTransportMethod": "FormRequestBody",
"TokenRequestContentType": "FormUrlEncoded",
"Scope": [ "https://api.example.com/.default" ],
"SetGrantTypeOnQueryString": false,
"CredentialsKeyNames": {
"client_id": "client_id",
"client_secret": "client_secret",
"grant_type": "grant_type"
},
"AccessTokenResponseOptions": {
"KeyNames": {
"AccessToken": "access_token",
"TokenType": "token_type",
"ExpiresIn": "expires_in"
}
}
},
"HttpClientFactoryEnabled": true,
"IgnoreRefreshTokens": false
}
}
}
}
OpenID Connect Authentication¶
OpenID Connect extends OAuth2 with validation settings:
{
"MyService": {
"OAuth2Authentication": {
/* OAuth2 configuration as above */,
"OpenIdConnect": {
"Authority": "https://login.microsoftonline.com/{tenant-id}/v2.0",
"ValidIssuers": [
"https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token"
],
"ValidAudiences": [ "your-client-id" ],
"ValidateLifetime": true,
"ValidateIssuerSigningKey": true,
"ClockSkew": "00:05:00",
"AdditionalTrustedSigningKeys": [],
"RequireHttpsMetadata": true
}
}
}
}
Resiliency Options¶
Standard Resilience Options¶
{
"MyService": {
"EnableHttpStandardResilience": true,
"HttpStandardResilience": {
"TotalRequestTimeout": {
"Timeout": "00:00:30"
},
"Retry": {
"MaxRetryAttempts": 3,
"BackoffType": "Constant",
"UseJitter": false,
"Delay": "00:00:02",
"MaxDelay": null
},
"CircuitBreaker": {
"FailureRatio": 0.1,
"MinimumThroughput": 2,
"SamplingDuration": "00:00:30",
"BreakDuration": "00:00:05"
},
"AttemptTimeout": {
"Timeout": "00:00:10"
},
"RateLimiter": {
"DefaultRateLimiterOptions": {
"PermitLimit": 1000,
"QueueLimit": 0,
"QueueProcessingOrder": "OldestFirst"
}
}
}
}
}
Standard Hedging Resilience Options¶
{
"MyService": {
"EnableHttpStandardHedgingResilience": true,
"HttpStandardHedgingResilience": {
"TotalRequestTimeout": {
"Timeout": "00:00:30"
},
"Hedging": {
"Delay": "00:00:02",
"MaxHedgedAttempts": 1
},
"Endpoint": {
"RateLimiter": {
"DefaultRateLimiterOptions": {
"PermitLimit": 1000,
"QueueLimit": 0
}
},
"CircuitBreaker": {
"FailureRatio": 0.1,
"MinimumThroughput": 2,
"SamplingDuration": "00:00:30",
"BreakDuration": "00:00:05"
},
"Timeout": {
"Timeout": "00:00:10"
}
}
}
}
}
Chaos Injection Options¶
{
"MyService": {
"EnableChaosInjection": true,
"ChaosInjection": {
"InjectionRate": 0.001,
"Latency": "00:00:05"
}
}
}
Options Details¶
- InjectionRate: Rate of injection (0.0 to 1.0). Default: 0.001 (0.1%)
- Latency: Latency to inject. Default: 30 seconds
Web Proxy Options¶
{
"MyService": {
"WebProxy": {
"UseProxy": true,
"ProxyAddress": "https://proxy.example.com:8080"
}
}
}
Options Details¶
- UseProxy: Whether to use a web proxy. Default:
false - ProxyAddress: Proxy server address (optional, required if
UseProxy=true)
Complete Configuration Examples¶
Example 1: API Key with Standard Resilience¶
{
"MyService": {
"BaseUrl": "https://api.example.com",
"DefaultTimeout": "00:00:30",
"WebProxy": {
"UseProxy": false
},
"EnableHttpStandardResilience": true,
"HttpStandardResilience": {
"TotalRequestTimeout": { "Timeout": "00:00:30" },
"Retry": {
"MaxRetryAttempts": 3,
"BackoffType": "Constant",
"Delay": "00:00:02"
},
"CircuitBreaker": {
"FailureRatio": 0.1,
"MinimumThroughput": 2,
"SamplingDuration": "00:00:30",
"BreakDuration": "00:00:05"
},
"AttemptTimeout": { "Timeout": "00:00:10" },
"RateLimiter": {
"DefaultRateLimiterOptions": {
"PermitLimit": 1000,
"QueueLimit": 0
}
}
},
"EnableHttpStandardHedgingResilience": false,
"HttpStandardHedgingResilience": {
/* Not used when disabled */
},
"EnableChaosInjection": false,
"ChaosInjection": {
"InjectionRate": 0.001,
"Latency": "00:00:05"
},
"ApiKeyAuthentication": {
"ApiKey": "your-api-key-here",
"HeaderName": "X-API-Key"
}
}
}
Example 2: OAuth2 with Hedging and Chaos¶
{
"MyService": {
"BaseUrl": "https://api.example.com",
"DefaultTimeout": "00:00:30",
"WebProxy": {
"UseProxy": false
},
"EnableHttpStandardResilience": false,
"EnableHttpStandardHedgingResilience": true,
"HttpStandardHedgingResilience": {
"TotalRequestTimeout": { "Timeout": "00:00:30" },
"Hedging": {
"Delay": "00:00:02",
"MaxHedgedAttempts": 1
},
"Endpoint": {
"RateLimiter": {
"DefaultRateLimiterOptions": {
"PermitLimit": 100,
"QueueLimit": 10
}
},
"CircuitBreaker": {
"FailureRatio": 0.1,
"MinimumThroughput": 5,
"SamplingDuration": "00:01:00",
"BreakDuration": "00:00:30"
},
"Timeout": { "Timeout": "00:00:10" }
}
},
"EnableChaosInjection": true,
"ChaosInjection": {
"InjectionRate": 0.1,
"Latency": "00:00:03"
},
"OAuth2Authentication": {
"ClientName": "MyService",
"OAuthHttpHandler": {
"OAuth2Options": {
"TokenEndpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret",
"GrantType": "ClientCredentials",
"Scope": [ "https://api.example.com/.default" ]
}
}
}
}
}
Configuration Binding¶
Service Registration¶
// Register options
services.AddMyServiceOptions(configuration);
// Register metrics (if UseMetrics=true)
services.AddMyServiceMetrics();
// Register service
services.AddMyServiceService();
Options Validation¶
The template includes automatic validation:
- DataAnnotations Validation: Required fields, data types, ranges
- Source-Generated Validators: Compile-time validation generation
- Startup Validation: Configuration validated at application startup
Validation Example¶
public sealed class MyServiceOptions
{
[Required]
[DataType(DataType.Url)]
required public string BaseUrl { get; set; }
[Required]
[Range(typeof(TimeSpan), "00:00:01", "00:05:00")]
required public TimeSpan DefaultTimeout { get; set; }
}
If validation fails, the application will throw an OptionsValidationException at startup.
Environment-Specific Configuration¶
appsettings.json (Base)¶
appsettings.Development.json¶
{
"MyService": {
"BaseUrl": "https://api.dev.example.com",
"DefaultTimeout": "00:01:00",
"EnableChaosInjection": true,
"ChaosInjection": {
"InjectionRate": 0.1
}
}
}
appsettings.Production.json¶
{
"MyService": {
"BaseUrl": "https://api.production.com",
"DefaultTimeout": "00:00:30",
"EnableChaosInjection": false,
"EnableHttpStandardResilience": true
}
}
Using Environment Variables¶
You can override configuration using environment variables:
# Windows
set MyService__BaseUrl=https://api.example.com
set MyService__ApiKeyAuthentication__ApiKey=your-key
# Linux/Mac
export MyService__BaseUrl=https://api.example.com
export MyService__ApiKeyAuthentication__ApiKey=your-key
Environment Variable Naming¶
- Use double underscore (
__) to represent nested properties - Prefix with section name (
MyService__) - Case-insensitive on Windows, case-sensitive on Linux/Mac
Secure Configuration¶
Azure Key Vault¶
builder.Configuration.AddAzureKeyVault(
new Uri("https://your-keyvault.vault.azure.net/"),
new DefaultAzureCredential());
User Secrets (Development)¶
Configuration in appsettings.json¶
{
"MyService": {
"ApiKeyAuthentication": {
"ApiKey": "" // Will be overridden by environment variable or Key Vault
}
}
}
Metrics Configuration¶
When UseMetrics=true, metrics are automatically configured. No additional configuration is required in appsettings.json. Metrics are registered via:
OpenTelemetry Integration¶
To export metrics to OpenTelemetry:
builder.Services.AddOpenTelemetry()
.WithMetrics(builder =>
{
builder.AddAspNetCoreInstrumentation()
.AddRuntimeInstrumentation()
.AddMeter("ConnectSoft.MyService")
.AddPrometheusExporter();
});
Best Practices¶
Configuration Organization¶
- Group Related Settings: Keep related settings together in nested objects
- Use Descriptive Names: Clear, descriptive property names
- Document Defaults: Document default values in code comments
Security¶
- Never Commit Secrets: Use environment variables, Key Vault, or User Secrets
- Validate Configuration: Always enable validation
- Use HTTPS: Always use HTTPS for API endpoints
Environment Management¶
- Separate Configurations: Use environment-specific configuration files
- Override Sensitive Values: Override sensitive values per environment
- Test Configurations: Test configurations in each environment
Troubleshooting¶
Configuration Not Loading¶
Problem: Options are null or default values.
Solutions:
- Verify section name matches (
MyService) - Check JSON syntax is valid
- Ensure configuration is added to
IConfiguration
Validation Failures¶
Problem: OptionsValidationException at startup.
Solutions:
- Check required fields are provided
- Verify data types match (e.g., TimeSpan format)
- Check range constraints are met
Environment Variables Not Working¶
Problem: Environment variables not overriding configuration.
Solutions:
- Verify naming convention (double underscore for nesting)
- Check environment variable is set correctly
- Ensure
AddEnvironmentVariables()is called
Conclusion¶
The ConnectSoft API Library Template provides a comprehensive configuration system using the Options pattern. By following the examples and best practices in this guide, you can configure your API library effectively and securely.
For more information, see:
- Authentication Guide - Authentication configuration details
- Resiliency Guide - Resiliency configuration
- Features Guide - Configuration features overview