Preparing Your Application for Deployment

Beginner 15 min read Lesson 1 of 5

Why Preparation Matters

Proper preparation ensures your application runs smoothly in production. Before deploying, you need to configure your application for the production environment.

Key Concept

Development and production environments have different requirements. Your application must be configured appropriately for each.

1. Configuration Management

Using appsettings.json for Different Environments

// appsettings.json - Base configuration
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

// appsettings.Development.json - Development overrides
{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft.AspNetCore": "Debug"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyApp;"
  }
}

// appsettings.Production.json - Production overrides
{
  "Logging": {
    "LogLevel": {
      "Default": "Error",
      "Microsoft.AspNetCore": "Error"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=production-server;Database=MyApp;"
  }
}

Environment Variables

// In Program.cs
var builder = WebApplication.CreateBuilder(args);

// Load environment-specific configuration
builder.Configuration
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
    .AddEnvironmentVariables();

// Get connection string from environment
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

2. Database Migration

// Using Entity Framework Core
// In Program.cs
using Microsoft.EntityFrameworkCore;

// Apply migrations automatically
using (var scope = app.Services.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService();
    dbContext.Database.Migrate();
}

// Or use command line
// dotnet ef database update

3. Logging Configuration

// Configure logging
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddDebug();

// Log to file (using Serilog or similar)
// Install: dotnet add package Serilog.AspNetCore
using Serilog;

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/myapp-.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

builder.Host.UseSerilog();

4. Error Handling

// In Program.cs
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

// Custom error page
app.UseStatusCodePagesWithReExecute("/Error/{0}");

// Global exception handling middleware
app.Use(async (context, next) =>
{
    try
    {
        await next();
    }
    catch (Exception ex)
    {
        // Log the error
        var logger = context.RequestServices.GetRequiredService>();
        logger.LogError(ex, "An unhandled exception occurred");

// Return a user-friendly error response
        context.Response.StatusCode = 500;
        await context.Response.WriteAsync("An error occurred. Please try again later.");
    }
});

5. Security Configuration

// HTTPS Redirection
app.UseHttpsRedirection();

// Security Headers
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    context.Response.Headers.Add("X-Frame-Options", "DENY");
    context.Response.Headers.Add("X-XSS-Protection", "1; mode=block");
    context.Response.Headers.Add("Referrer-Policy", "strict-origin-when-cross-origin");
    await next();
});

// CORS Configuration
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowSpecificOrigin",
        builder => builder
            .WithOrigins("https://yourdomain.com")
            .AllowAnyMethod()
            .AllowAnyHeader());
});

6. Performance Optimization

// Enable Response Compression
builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
});

// Use in app
app.UseResponseCompression();

// Cache static files
app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=31536000");
    }
});

// Bundle and minify CSS/JS
// Use WebOptimizer or bundling

7. Health Checks

// Add health checks
builder.Services.AddHealthChecks()
    .AddDbContextCheck()
    .AddUrlGroup(new Uri("https://api.example.com"), "API Health")
    .AddCheck("Custom Check");

// In app
app.MapHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

8. Build Configuration

// In .csproj file

    net10.0
    enable
    enable
    
    true


// Build for production
// dotnet build -c Release
// dotnet publish -c Release -o ./publish

Complete Deployment Preparation Checklist

Pre-Deployment Checklist
  • ✅ Configure appsettings for production
  • ✅ Set up environment variables
  • ✅ Apply database migrations
  • ✅ Configure logging for production
  • ✅ Implement error handling
  • ✅ Add security headers and HTTPS
  • ✅ Enable caching and compression
  • ✅ Add health checks
  • ✅ Build in Release mode
  • ✅ Test in production-like environment
  • ✅ Backup database and files
  • ✅ Update documentation
Key Takeaway

Proper preparation is essential for successful deployment. Configure your application for the production environment, implement security measures, and optimize performance.

Exercise

Prepare your application for deployment:

  1. Create appsettings.Production.json
  2. Set up environment variables
  3. Configure logging for production
  4. Add security headers
  5. Enable response compression
  6. Create a deployment checklist
Test Your Knowledge - Take Quiz