Skip to content

Latest commit

Β 

History

442 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

dotenv.net

Build, Test & Coverage License: MIT codecov NuGet Version

project icon

dotenv.net is a lightweight library for loading environment variables from .env files in .NET applications. It keeps sensitive configuration out of source code and supports a range of options to suit different project setups.

Installation

Install via NuGet using any of the following methods:

.NET CLI

dotnet add package dotenv.net

Package Manager Console

Install-Package dotenv.net

PackageReference

<PackageReference Include="dotenv.net" Version="4.x.x"/>

Quick Start

using dotenv.net;

// Load .env from the application directory into the system environment
DotEnv.Load();

// Read variables from .env without modifying the system environment
var envVars = DotEnv.Read();
Console.WriteLine(envVars["DATABASE_URL"]);

By default, both methods look for a .env file in the same directory as the application executable.

Configuration Options

Both Load() and Read() accept a DotEnvOptions instance to customise behaviour.

DotEnv.Load(options: new DotEnvOptions(
    ignoreExceptions: false,           // Throw on errors instead of silently failing (default: true)
    envFilePaths: ["./config/.env"],   // One or more paths to .env files (default: [".env"])
    encoding: Encoding.UTF8,           // File encoding (default: UTF-8)
    trimValues: true,                  // Strip whitespace from values (default: false)
    overwriteExistingVars: false,      // Skip vars already set in the environment (default: true)
    probeForEnv: true,                 // Search parent directories for a .env file (default: false)
    probeLevelsToSearch: 3,            // How many directory levels to ascend when probing (default: 4)
    supportExportSyntax: true,         // Support `export KEY=VALUE` syntax (default: false)
    supportInlineComments: true,       // Strip `# comment` from unquoted values (default: true)
    supportVariableExpansion: true,    // Expand ${VAR} and $VAR variable references (default: true)
    environmentCascade: true,          // Load layered .env / .env.local / .env.{Environment} files (default: false)
    environmentName: "Development"     // Optional explicit environment for cascade loading
));

Note: probeForEnv and custom envFilePaths are mutually exclusive. environmentCascade cannot be combined with custom envFilePaths or envStreams. environmentCascade can be used together with probeForEnv. Setting conflicting options will throw an InvalidOperationException.

Loading multiple .env files

DotEnv.Load(options: new DotEnvOptions(
    envFilePaths: ["./config/.env", "./secrets/.env"]
));

When overwriteExistingVars is false, keys from earlier files take precedence over those in later files.

Environment cascading (hierarchical loading)

Opt-in hierarchical loading resolves layered .env files from the same directory as .env (or from the probed directory when probeForEnv is enabled). Later files override earlier files when overwriteExistingVars is true (the default):

  1. .env
  2. .env.local
  3. .env.{Environment} (only when an environment name is known)
  4. .env.{Environment}.local (only when an environment name is known)

The environment name is resolved in this order: an explicit name passed to WithEnvironmentCascade, then ASPNETCORE_ENVIRONMENT, DOTNET_ENVIRONMENT, and DOTENV_ENV. If none are set, only .env and .env.local are considered. Missing files in the cascade are skipped. Add *.local to .gitignore so machine-specific secrets are not committed.

DotEnv.Fluent()
    .WithEnvironmentCascade()                 // uses ASPNETCORE_ENVIRONMENT / DOTNET_ENVIRONMENT / DOTENV_ENV
    .Load();

DotEnv.Fluent()
    .WithEnvironmentCascade("Production")     // explicit environment name
    .WithProbeForEnv()                        // cascade + probe is allowed
    .Load();

WithEnvironmentCascade() cannot be combined with custom WithEnvFiles(...) paths or WithEnvStreams(...).

Fluent API

DotEnv.Fluent() returns a DotEnvOptions instance that exposes a chainable builder API, useful when you prefer an explicit, readable configuration style.

Loading variables:

DotEnv.Fluent()
    .WithExceptions()
    .WithEnvFiles("./config/.env")
    .WithTrimValues()
    .WithEncoding(Encoding.UTF8)
    .WithOverwriteExistingVars()
    .WithProbeForEnv(probeLevelsToSearch: 6)
    .WithSupportExportSyntax()
    .Load();

Reading variables without writing to the environment:

var envVars = DotEnv.Fluent()
    .WithoutExceptions()
    .WithEnvFiles()               // Defaults to .env
    .WithoutTrimValues()
    .WithEncoding(Encoding.UTF8)
    .WithoutOverwriteExistingVars()
    .WithoutProbeForEnv()
    .WithoutSupportExportSyntax()
    .Read();

Fluent builder methods

Method Description
WithExceptions() Throw exceptions on errors
WithoutExceptions() Silently ignore errors (default)
WithEnvFiles(params string[]) Specify one or more .env file paths
WithEncoding(Encoding) Set file encoding
WithTrimValues() Strip whitespace from values
WithoutTrimValues() Preserve whitespace in values (default)
WithOverwriteExistingVars() Overwrite existing environment variables (default)
WithoutOverwriteExistingVars() Preserve existing environment variables
WithProbeForEnv(int) Search parent directories for a .env file
WithoutProbeForEnv() Disable parent directory search (default)
WithSupportExportSyntax() Support export KEY=VALUE syntax
WithoutSupportExportSyntax() Disable export syntax support (default)
WithSupportInlineComments() Strip # comment from unquoted values (default)
WithoutSupportInlineComments() Preserve inline comments in values
WithSupportVariableExpansion() Enable variable expansion and interpolation
WithoutSupportVariableExpansion() Disable variable expansion and interpolation (default)
WithVariableExpansion() Alias for WithSupportVariableExpansion()
WithoutVariableExpansion() Alias for WithoutSupportVariableExpansion()
WithEnvironmentCascade(string?) Load .env, .env.local, and environment-specific files
WithoutEnvironmentCascade() Disable hierarchical loading (default)

Variable Expansion & Interpolation

dotenv.net supports variable expansion (substitution), allowing values to reference other variables or system environment settings using ${VAR} or $VAR syntax:

BASE_URL=https://api.example.com
API_ENDPOINT=${BASE_URL}/v1
PORT=8080
DATABASE_URL=postgres://${USER}:${PASSWORD}@localhost:${PORT}/db

Syntax and Features

  • Braced variables: ${VAR} expands to the value of VAR.
  • Short variables: $VAR expands VAR matching [A-Za-z_][A-Za-z0-9_]*. Dollar signs not followed by a valid identifier (e.g. $100 or a trailing $) are preserved literally.
  • Default fallbacks:
    • ${VAR:-default}: Evaluates to default if VAR is unset or empty.
    • ${VAR-default}: Evaluates to default if VAR is unset (preserves an explicitly set empty value).
  • Nested expressions: Fallbacks can be nested, e.g. ${CUSTOM_URL:-${DEFAULT_HOST:-localhost}:3000}.
  • Resolution hierarchy: Variables are resolved sequentially in document order against earlier parsed keys, cascading to System.Environment if not set in the .env file. Missing variables without a default resolve to an empty string.

Quoting and Escaping

  • Single quotes ('...'): Treated as raw literals. Variables inside single quotes are never expanded (e.g. '${NOT_EXPANDED}' remains literal ${NOT_EXPANDED}).
  • Double quotes ("...") and unquoted values: Variable expansion is enabled.
  • Backslash escaping: Preceding a dollar sign with a backslash prevents expansion (e.g. \${VAR} evaluates to ${VAR}, and \$VAR evaluates to $VAR).

Circular Dependency Protection

Circular references (such as direct A=${A} or indirect A=${B}, B=${A}) are detected automatically:

  • When ignoreExceptions is false, an InvalidOperationException is thrown identifying the cycle path.
  • When ignoreExceptions is true, the cyclic reference resolves safely to an empty string without crashing or causing a stack overflow.

To enable variable expansion:

DotEnv.Fluent()
    .WithVariableExpansion()
    .Load();

Reading Variables

DotEnv.Read() returns an IDictionary<string, string> of the parsed key-value pairs without writing anything to the system environment. This is useful for inspecting values or selectively applying them.

var envVars = DotEnv.Read();

if (envVars.TryGetValue("API_KEY", out var apiKey))
{
    // use apiKey
}

EnvReader Utility

The dotenv.net.Utilities namespace provides EnvReader, a helper class for reading strongly-typed values directly from the system environment (i.e., after calling DotEnv.Load()).

using dotenv.net.Utilities;

var host = EnvReader.GetStringValue("DB_HOST");
var port = EnvReader.GetIntValue("DB_PORT");
var enabled = EnvReader.GetBooleanValue("FEATURE_FLAG");

For non-throwing alternatives, use the TryGet* methods:

if (EnvReader.TryGetIntValue("DB_PORT", out var port))
{
    // port is valid
}

Available methods

Method Return Type Throws if missing
HasValue(string key) bool No
GetStringValue(string key) string Yes
GetIntValue(string key) int Yes
GetDoubleValue(string key) double Yes
GetDecimalValue(string key) decimal Yes
GetBooleanValue(string key) bool Yes
TryGetStringValue(string key, out string value) bool No, returns null on failure
TryGetIntValue(string key, out int value) bool No, returns 0 on failure
TryGetDoubleValue(string key, out double value) bool No, returns 0.0 on failure
TryGetDecimalValue(string key, out decimal value) bool No, returns 0.0m on failure
TryGetBooleanValue(string key, out bool value) bool No, returns false on failure

Contributing

Contributions are welcome. If you have a bug report, feature request, or improvement in mind, please open an issue or submit a pull request.

To get started:

  1. Fork the repository and create a feature branch.
  2. Make your changes and ensure existing tests still pass.
  3. Add tests for any new behaviour.
  4. Open a pull request with a clear description of what was changed and why.

The project targets .NET and uses the standard dotnet CLI toolchain. Run the test suite with:

dotnet test

Contributors

Thanks to everyone who has contributed to dotenv.net:

@bolorundurowb @joliveros @vizeke @merqlove @tracker1 @NaturalWill @texyh @jonlabelle @Gounlaf @DTTerastar @Mondonno @caveman-dick @VijoPlays @bobbyg603 @Moha-sami

License

dotenv.net is licensed under the MIT License. See the LICENSE file for details.

Happy Coding! πŸš€

About

πŸ” A library to read .env files in a .NET Core environment

Topics

Resources

Stars

302 stars

Watchers

4 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages