Skip to main content

Overview

RealtimeChat uses ASP.NET Core’s configuration system with environment-specific settings files. Configuration is managed through appsettings.json files, environment variables, and user secrets.

Configuration Files

The application uses three main configuration files:
Base configuration for all environments:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "AllowCorsAddress": "http://localhost:5173",
  "ConnectionStrings": {
    "DefaultConnectionString": "Server=localhost;Port=5432;Username=postgres;Password=postgres;Database=realtime_chat_db;Include Error Detail=true;MaxPoolSize=10;MinPoolSize=2;"
  }
}

Configuration Structure

Database Connection

The connection string is configured under ConnectionStrings:DefaultConnectionString:
{
  "ConnectionStrings": {
    "DefaultConnectionString": "Server=localhost;Port=5432;Username=postgres;Password=postgres;Database=realtime_chat_db;Include Error Detail=true;MaxPoolSize=10;MinPoolSize=2;"
  }
}

Connection String Parameters

ParameterDescriptionExample
ServerPostgreSQL hostlocalhost, host.docker.internal, db.example.com
PortPostgreSQL port5432
UsernameDatabase userpostgres, admin
PasswordDatabase passwordpostgres, secure_password
DatabaseDatabase namerealtime_chat_db
Include Error DetailShow detailed errorstrue (dev only)
MaxPoolSizeMaximum connections10 (production)
MinPoolSizeMinimum connections2 (production)
Remove Include Error Detail=true in production as it may expose sensitive information. Also ensure MaxPoolSize and MinPoolSize are configured for optimal performance.

CORS Configuration

CORS is configured via the AllowCorsAddress setting:
{
  "AllowCorsAddress": "http://localhost:5173"
}
This controls which origins can access the API. The application reads this value and configures CORS accordingly:
// From Program.cs
builder.AddCors();

// CORS middleware
app.UseCors();
{
  "AllowCorsAddress": "http://localhost:5173"
}

Logging Configuration

ASP.NET Core logging is configured under the Logging section:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.EntityFrameworkCore": "Warning"
    }
  }
}

Log Levels

Most detailed logs. Use for development debugging only.
{ "Default": "Trace" }
Detailed information for debugging.
{ "Default": "Debug" }
General informational messages (recommended for development).
{ "Default": "Information" }
Warning messages for unexpected events.
{ "Default": "Warning" }
Error messages (recommended for production).
{ "Default": "Error" }
Critical failures requiring immediate attention.
{ "Default": "Critical" }

Authentication Settings

The application uses ASP.NET Core Identity with cookie-based authentication:
// From Program.cs
builder.AddAuth();      // Configures Identity
builder.AddCookies();   // Configures cookie authentication

app.UseAuth();          // Applies authentication middleware
Authentication configuration is handled in extension methods. Identity uses the following defaults:
  • Password requirements (configurable)
  • Cookie expiration
  • Lockout policies
  • Token providers

Database Context Configuration

The database context is configured in ServiceCollectionExtensions.cs:
public static void AddDbContext(
    this IServiceCollection services,
    IConfiguration configuration,
    IHostEnvironment environment)
{
    var connectionString = configuration
        .GetConnectionString("DefaultConnectionString");
    
    services.AddDbContextFactory<RealtimeChatDbContext>(optionsBuilder =>
    {
        var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
        dataSourceBuilder.UseJsonNet();
        
        optionsBuilder.UseNpgsql(dataSourceBuilder.Build(),
            contextOptionsBuilder =>
            {
                contextOptionsBuilder
                    .UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery);
            });
            
        if (!environment.IsDevelopment())
        {
            return;
        }

        var loggerFactory = LoggerFactory
            .Create(loggingBuilder => 
                loggingBuilder.AddConsole());
        
        optionsBuilder
            .UseLoggerFactory(loggerFactory)
            .EnableSensitiveDataLogging()
            .EnableDetailedErrors();
    });
}
In development mode, the context enables sensitive data logging and detailed errors for easier debugging.

Environment Variables

All configuration can be overridden using environment variables with the following syntax:
# Connection string
export ConnectionStrings__DefaultConnectionString="Server=prod-db;Port=5432;Database=realtime_chat_db;Username=admin;Password=secure_pass"

# CORS address
export AllowCorsAddress="https://app.example.com"

# Logging
export Logging__LogLevel__Default="Warning"
export Logging__LogLevel__Microsoft__AspNetCore="Error"

# ASP.NET Core environment
export ASPNETCORE_ENVIRONMENT="Production"
Use double underscores (__) to represent nested configuration keys in environment variables.

Docker Environment Variables

When running in Docker, configure via docker-compose.yml:
services:
  realtimechat:
    image: realtimechat:latest
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ConnectionStrings__DefaultConnectionString=Server=db;Port=5432;Database=realtime_chat_db;Username=admin;Password=${DB_PASSWORD}
      - AllowCorsAddress=https://app.example.com
      - Logging__LogLevel__Default=Warning

User Secrets (Development)

For local development, use User Secrets to store sensitive data:
1

Initialize User Secrets

dotnet user-secrets init --project Applications/RealtimeChat.API
2

Set Secret Values

dotnet user-secrets set "ConnectionStrings:DefaultConnectionString" \
  "Server=localhost;Port=5432;Database=realtime_chat_db;Username=postgres;Password=my_secret_password" \
  --project Applications/RealtimeChat.API
3

List Secrets

dotnet user-secrets list --project Applications/RealtimeChat.API
4

Remove Secrets

dotnet user-secrets remove "ConnectionStrings:DefaultConnectionString" \
  --project Applications/RealtimeChat.API
User secrets are stored in plain text on your local machine. They are only suitable for development, not production.

GraphQL Configuration

The application uses Hot Chocolate for GraphQL:
// From Program.cs
builder.Services.AddGraphQlServer<RealtimeChatDbContext>(env);

app.UseGraphQlServer(args);
GraphQL endpoints are typically available at:
  • /graphql - GraphQL endpoint
  • /graphql/playground - Interactive GraphQL IDE (development only)

Environment-Specific Behavior

Development Mode

When ASPNETCORE_ENVIRONMENT=Development:
  • Detailed error pages
  • Sensitive data logging enabled
  • GraphQL playground available
  • Swagger/OpenAPI endpoints exposed (if configured)
  • Console logging with detailed EF Core queries

Production Mode

When ASPNETCORE_ENVIRONMENT=Production:
  • Generic error pages
  • Minimal logging
  • No sensitive data in logs
  • GraphQL playground disabled
  • Connection pooling enforced

Docker Mode

When ASPNETCORE_ENVIRONMENT=Docker:
  • Uses host.docker.internal for database connection
  • Configured for container networking
  • Production-like security settings

Configuration Best Practices

1

Never Commit Secrets

Use .gitignore to exclude sensitive configuration:
appsettings.Production.json
appsettings.*.local.json
*.user
secrets.json
2

Use Environment Variables in Production

Override configuration with environment variables instead of modifying config files:
export ConnectionStrings__DefaultConnectionString="..."
3

Separate Dev and Prod Configs

Keep development and production configurations completely separate:
  • appsettings.Development.json - Local development
  • appsettings.Docker.json - Docker containers
  • Environment variables - Production deployment
4

Use Configuration Validation

Validate configuration at startup:
var connectionString = configuration.GetConnectionString("DefaultConnectionString");
if (string.IsNullOrEmpty(connectionString))
{
    throw new InvalidOperationException("Database connection string not configured");
}
5

Document Required Settings

Create a .env.example file documenting required configuration:
# Database Configuration
ConnectionStrings__DefaultConnectionString=Server=localhost;Port=5432;...

# CORS Configuration
AllowCorsAddress=http://localhost:5173

# Environment
ASPNETCORE_ENVIRONMENT=Production

Configuration Precedence

ASP.NET Core loads configuration in the following order (later sources override earlier ones):
  1. appsettings.json
  2. appsettings.{Environment}.json
  3. User Secrets (Development only)
  4. Environment variables
  5. Command-line arguments
This means environment variables will always override settings in appsettings.json files.

Troubleshooting

Check the configuration precedence order. Environment variables may be overriding your appsettings.json values.Debug by inspecting the configuration at runtime:
var config = app.Configuration.GetSection("ConnectionStrings");
foreach (var item in config.AsEnumerable())
{
    Console.WriteLine($"{item.Key} = {item.Value}");
}
Verify the AllowCorsAddress setting matches your frontend origin exactly:
{
  "AllowCorsAddress": "http://localhost:5173"
}
Ensure there’s no trailing slash and the protocol (http/https) matches.
Test the connection string format:
psql "Server=localhost;Port=5432;Database=realtime_chat_db;Username=postgres;Password=postgres"
Common issues:
  • Wrong host (localhost vs 127.0.0.1 vs host.docker.internal)
  • Firewall blocking port 5432
  • Incorrect credentials
  • Database doesn’t exist

Next Steps

Build docs developers (and LLMs) love