Strongly-typed, validated environment variables for .NET. Fail fast at startup, not in production.
// Scattered across your codebase, crashes at runtime:
var connStr = Environment.GetEnvironmentVariable("DATABASE_URL"); // null in prod = π₯
var timeout = int.Parse(config["HttpClient:TimeoutSeconds"]!); // "thirty" = FormatException
var apiKey = config["OpenAI:ApiKey"]; // empty string = silent failureYou deploy, everything looks fine, then 10 minutes later a request hits a code path with a missing config value. Boom.
using EnvGuard;
public class AppConfig
{
[EnvVar("DATABASE_URL", Required = true)]
public string DatabaseUrl { get; set; } = "";
[EnvVar("OPENAI_API_KEY", Required = true, Description = "OpenAI API key")]
public string OpenAiApiKey { get; set; } = "";
[EnvVar("HTTP_TIMEOUT_SECONDS", Default = "30")]
public int HttpTimeoutSeconds { get; set; }
[EnvVar("ENABLE_CACHE", Default = "true")]
public bool EnableCache { get; set; }
[EnvVar("LOG_LEVEL", Default = "Information")]
public LogLevel LogLevel { get; set; }
[EnvVar("ALLOWED_ORIGINS")] // Optional
public string? AllowedOrigins { get; set; }
}// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEnvGuard<AppConfig>(); // validates ALL vars at startupIf DATABASE_URL or OPENAI_API_KEY are missing, your app won't start:
EnvGuardException: 2 required environment variables are missing or invalid:
DATABASE_URL β Required, not set
OPENAI_API_KEY β Required, not set (OpenAI API key)
All errors at once. Not one at a time. Not at runtime.
app.MapGet("/health", (AppConfig config) => new {
timeout = config.HttpTimeoutSeconds, // int, not string
cache = config.EnableCache, // bool, not string
level = config.LogLevel // enum, not string
});dotnet add package EnvGuard| Type | Example Value | Notes |
|---|---|---|
string |
"hello" |
No conversion |
int |
"8080" |
int.Parse |
long |
"9999999999" |
long.Parse |
double |
"3.14" |
double.Parse |
bool |
"true", "1", "yes", "on" |
Case-insensitive, multiple formats |
enum |
"Warning" |
Case-insensitive Enum.Parse |
Uri |
"https://example.com" |
new Uri(...) |
TimeSpan |
"00:05:00" or "300" |
Parses format or total seconds |
Guid |
"a1b2c3..." |
Guid.Parse |
T? |
Any of above | Nullable wrapper β left null if not set |
Accepts: true/false, 1/0, yes/no, on/off (case-insensitive).
[EnvVar("PORT", Default = "8080")]
public int Port { get; set; } // Uses 8080 if PORT is not set[EnvVar("OPENAI_API_KEY", Required = true, Description = "Get one at platform.openai.com")]
public string ApiKey { get; set; } = "";
// Error: OPENAI_API_KEY β Required, not set (Get one at platform.openai.com)var errors = EnvGuardValidator.Check<AppConfig>();
if (errors.Count > 0)
foreach (var err in errors)
Console.WriteLine($" β {err}");var config = EnvGuardValidator.Validate<AppConfig>();var testEnv = new Dictionary<string, string>
{
["DATABASE_URL"] = "sqlite://test.db",
["API_KEY"] = "test-key"
};
var config = EnvGuardValidator.Validate<AppConfig>(
name => testEnv.GetValueOrDefault(name));| Feature | IOptions<T> |
EnvGuard |
|---|---|---|
| Missing values | Silent default(T) |
Throws at startup |
| All errors at once | No | Yes |
| Type coercion | Bind from config | int, bool, enum, Uri, TimeSpan, Guid |
| Bool formats | Only true/false |
true/1/yes/on |
| Testable | Needs IConfiguration mock |
Simple Func<string, string?> |
| Dependencies | Microsoft.Extensions.* |
Zero (netstandard2.0) |
MIT