The Ultimate ASP.NET Core Cheat Sheet: Full-Stack Web Development Guide

Introduction: What is ASP.NET Core?

ASP.NET Core is a cross-platform, high-performance, open-source framework for building modern web applications that run on Windows, Linux, and macOS. It represents a redesign of ASP.NET that unifies the previously separate ASP.NET MVC and ASP.NET Web API into a single programming model. Built with a modular architecture, ASP.NET Core allows developers to create web applications, APIs, real-time hubs, and full-stack web solutions with superior performance, security, and scalability.

Core ASP.NET Core Concepts

Framework Architecture

  • Modular Design: Components can be included via NuGet packages
  • Middleware Pipeline: Request processing through configurable components
  • Dependency Injection: Built-in IoC container for loose coupling
  • Configuration System: Environment-based settings from multiple sources
  • Hosting Model: Flexibility to self-host or run under IIS/Apache/Nginx

Application Models

  • MVC (Model-View-Controller): Structured pattern for web applications
  • Razor Pages: Page-based model for simpler web UI development
  • Blazor: Component-based UI framework using C# instead of JavaScript
  • Web API: RESTful service development
  • gRPC: High-performance RPC framework
  • SignalR: Real-time web functionality

ASP.NET Core Project Structure

Key Files

  • Program.cs: Application entry point and configuration
  • appsettings.json: Configuration settings
  • Startup.cs (older versions): App configuration and service setup
  • wwwroot/: Static files (CSS, JS, images)
  • Controllers/: For MVC/API controllers
  • Views/: For MVC views
  • Pages/: For Razor Pages
  • Models/: For data models
  • Data/: For database context and migrations

Configuration Flow

// Program.cs in ASP.NET Core 6+
var builder = WebApplication.CreateBuilder(args);

// Service configuration
builder.Services.AddControllers();
builder.Services.AddDbContext<ApplicationDbContext>();

var app = builder.Build();

// Middleware configuration
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

app.MapControllers();

app.Run();

MVC Development

Controller Basics

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    
    public ProductsController(ApplicationDbContext context)
    {
        _context = context;
    }
    
    [HttpGet]
    public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
    {
        return await _context.Products.ToListAsync();
    }
    
    [HttpGet("{id}")]
    public async Task<ActionResult<Product>> GetProduct(int id)
    {
        var product = await _context.Products.FindAsync(id);
        
        if (product == null)
        {
            return NotFound();
        }
        
        return product;
    }
    
    [HttpPost]
    public async Task<ActionResult<Product>> PostProduct(Product product)
    {
        _context.Products.Add(product);
        await _context.SaveChangesAsync();
        
        return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
    }
}

Razor View Basics

@model Product

<h1>@Model.Name</h1>
<p>Price: @Model.Price.ToString("C")</p>

@if (Model.IsInStock)
{
    <button>Add to Cart</button>
}
else
{
    <p>Out of stock</p>
}

Tag Helpers

<a asp-controller="Home" asp-action="Index">Home</a>
<form asp-controller="Account" asp-action="Login" method="post">
    <div>
        <label asp-for="Email"></label>
        <input asp-for="Email">
        <span asp-validation-for="Email"></span>
    </div>
    <button type="submit">Login</button>
</form>

Razor Pages

PageModel Structure

public class CreateModel : PageModel
{
    private readonly ApplicationDbContext _context;
    
    public CreateModel(ApplicationDbContext context)
    {
        _context = context;
    }
    
    [BindProperty]
    public Product Product { get; set; }
    
    public IActionResult OnGet()
    {
        return Page();
    }
    
    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }
        
        _context.Products.Add(Product);
        await _context.SaveChangesAsync();
        
        return RedirectToPage("./Index");
    }
}

Razor Page Markup

@page
@model CreateModel
@{
    ViewData["Title"] = "Create Product";
}

<h1>@ViewData["Title"]</h1>

<form method="post">
    <div class="form-group">
        <label asp-for="Product.Name"></label>
        <input asp-for="Product.Name" class="form-control" />
        <span asp-validation-for="Product.Name" class="text-danger"></span>
    </div>
    
    <div class="form-group">
        <label asp-for="Product.Price"></label>
        <input asp-for="Product.Price" class="form-control" />
        <span asp-validation-for="Product.Price" class="text-danger"></span>
    </div>
    
    <button type="submit" class="btn btn-primary">Create</button>
</form>

Blazor Development

Blazor Component

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Increment</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Blazor Server vs WebAssembly vs Web App

FeatureBlazor ServerBlazor WebAssemblyBlazor Web App
ExecutionServer-sideClient-side (browser)Both server and client
Initial LoadFastSlower (downloads .NET runtime)Configurable
Network DependencyConstant connection requiredOnly for API callsAdaptable
Hardware RequirementsHigher server resourcesHigher client resourcesFlexible
Offline SupportNonePossibleConfigurable
Integration with Existing AppsEasierCan be isolatedMost flexible

API Development

Minimal API Example

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapGet("/todos", async (TodoDb db) =>
    await db.Todos.ToListAsync());

app.MapGet("/todos/{id}", async (int id, TodoDb db) =>
    await db.Todos.FindAsync(id) is Todo todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.MapPost("/todos", async (Todo todo, TodoDb db) =>
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($"/todos/{todo.Id}", todo);
});

app.Run();

OpenAPI/Swagger Integration

// Add to Program.cs
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { 
        Title = "My API", 
        Version = "v1",
        Description = "A simple API example"
    });
});

// In middleware pipeline
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1"));
}

Authentication & Authorization

JWT Authentication Setup

// Add services
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        ValidAudience = builder.Configuration["JWT:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(
            Encoding.UTF8.GetBytes(builder.Configuration["JWT:Secret"]))
    };
});

// Add middleware
app.UseAuthentication();
app.UseAuthorization();

Authorization Policies

// Setup policies
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy => 
        policy.RequireRole("Administrator"));
    
    options.AddPolicy("RequireMfa", policy => 
        policy.RequireClaim("amr", "mfa"));
});

// Use in controllers/endpoints
[Authorize(Policy = "AdminOnly")]
public IActionResult AdminDashboard()
{
    return View();
}

Data Access with Entity Framework Core

DbContext Setup

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
    
    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>()
            .HasOne(p => p.Category)
            .WithMany(c => c.Products)
            .HasForeignKey(p => p.CategoryId);
            
        modelBuilder.Entity<Category>()
            .HasData(
                new Category { Id = 1, Name = "Electronics" },
                new Category { Id = 2, Name = "Books" }
            );
    }
}

Common EF Core Operations

// Adding entity
_context.Products.Add(new Product { Name = "Laptop", Price = 999.99m });
await _context.SaveChangesAsync();

// Querying with filtering
var expensiveProducts = await _context.Products
    .Where(p => p.Price > 500)
    .ToListAsync();

// Include related data
var productsWithCategories = await _context.Products
    .Include(p => p.Category)
    .ToListAsync();

// Update entity
var product = await _context.Products.FindAsync(1);
product.Price = 899.99m;
await _context.SaveChangesAsync();

// Delete entity
var productToDelete = await _context.Products.FindAsync(2);
_context.Products.Remove(productToDelete);
await _context.SaveChangesAsync();

Configuration and Options Pattern

Configuration Setup

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

// Configuration sources are already set up in CreateBuilder
// Access configuration
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

// Strongly-typed configuration
builder.Services.Configure<SmtpSettings>(
    builder.Configuration.GetSection("SmtpSettings"));

Using Options Pattern

// Options class
public class SmtpSettings
{
    public string Server { get; set; }
    public int Port { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

// In a service
public class EmailService
{
    private readonly SmtpSettings _smtpSettings;
    
    public EmailService(IOptions<SmtpSettings> smtpSettings)
    {
        _smtpSettings = smtpSettings.Value;
    }
    
    public void SendEmail(string to, string subject, string body)
    {
        // Use _smtpSettings to send email
    }
}

Dependency Injection

Service Lifetimes

// Transient: New instance created for each request
builder.Services.AddTransient<ITransientService, TransientService>();

// Scoped: New instance created for each HTTP request
builder.Services.AddScoped<IScopedService, ScopedService>();

// Singleton: Single instance for application lifetime
builder.Services.AddSingleton<ISingletonService, SingletonService>();

Service Registration Patterns

// Interface-based injection
builder.Services.AddScoped<IProductRepository, SqlProductRepository>();

// Concrete class injection
builder.Services.AddScoped<ProductService>();

// Factory-based injection
builder.Services.AddSingleton<IHttpClientFactory, HttpClientFactory>();
builder.Services.AddHttpClient("github", c =>
{
    c.BaseAddress = new Uri("https://api.github.com/");
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory");
});

Middleware Components

Custom Middleware

public class RequestLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestLoggingMiddleware> _logger;
    
    public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }
    
    public async Task InvokeAsync(HttpContext context)
    {
        _logger.LogInformation($"Request: {context.Request.Method} {context.Request.Path}");
        
        // Call the next middleware in the pipeline
        await _next(context);
        
        _logger.LogInformation($"Response: {context.Response.StatusCode}");
    }
}

// Extension method for cleaner registration
public static class RequestLoggingMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestLogging(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestLoggingMiddleware>();
    }
}

// In Program.cs
app.UseRequestLogging();

Built-in Middleware (in typical order)

// Exception handling
app.UseExceptionHandler("/Error");

// HTTPS redirection
app.UseHttpsRedirection();

// Static files
app.UseStaticFiles();

// Cookie policy
app.UseCookiePolicy();

// Routing
app.UseRouting();

// CORS
app.UseCors("MyCorsPolicyName");

// Authentication
app.UseAuthentication();

// Authorization
app.UseAuthorization();

// Response compression
app.UseResponseCompression();

// Response caching
app.UseResponseCaching();

// Endpoint execution
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapRazorPages();
    endpoints.MapBlazorHub();
});

Handling Common Web Tasks

Form Validation

// Model with validation attributes
public class ProductViewModel
{
    [Required]
    [StringLength(100, MinimumLength = 3)]
    public string Name { get; set; }
    
    [Required]
    [Range(0.01, 10000)]
    [DataType(DataType.Currency)]
    public decimal Price { get; set; }
    
    [Required]
    [Display(Name = "Category")]
    public int CategoryId { get; set; }
}

// In controller
[HttpPost]
public async Task<IActionResult> Create(ProductViewModel model)
{
    if (!ModelState.IsValid)
    {
        // Return view with errors
        return View(model);
    }
    
    // Process valid form
    var product = new Product
    {
        Name = model.Name,
        Price = model.Price,
        CategoryId = model.CategoryId
    };
    
    _context.Products.Add(product);
    await _context.SaveChangesAsync();
    
    return RedirectToAction(nameof(Index));
}

File Upload Handling

// File upload in model
public class ProductUploadModel
{
    [Required]
    public string Name { get; set; }
    
    [Required]
    public IFormFile ImageFile { get; set; }
}

// In controller
[HttpPost]
public async Task<IActionResult> Upload(ProductUploadModel model)
{
    if (ModelState.IsValid)
    {
        // Process file
        var fileName = Guid.NewGuid().ToString() + Path.GetExtension(model.ImageFile.FileName);
        var filePath = Path.Combine(_environment.WebRootPath, "uploads", fileName);
        
        using (var fileStream = new FileStream(filePath, FileMode.Create))
        {
            await model.ImageFile.CopyToAsync(fileStream);
        }
        
        // Save product with image path
        var product = new Product
        {
            Name = model.Name,
            ImagePath = "/uploads/" + fileName
        };
        
        _context.Products.Add(product);
        await _context.SaveChangesAsync();
        
        return RedirectToAction(nameof(Index));
    }
    
    return View(model);
}

Error Handling

// Global exception handling in Program.cs
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseStatusCodePagesWithReExecute("/Error/{0}");
    app.UseHsts();
}

// Error controller
[AllowAnonymous]
public class ErrorController : Controller
{
    [Route("Error")]
    public IActionResult Error()
    {
        var exceptionHandlerPathFeature = 
            HttpContext.Features.Get<IExceptionHandlerPathFeature>();
            
        // Log the exception
        _logger.LogError(exceptionHandlerPathFeature?.Error, "Unhandled exception");
        
        return View();
    }
    
    [Route("Error/{statusCode}")]
    public IActionResult StatusCodeError(int statusCode)
    {
        var statusCodeReExecuteFeature = 
            HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
            
        ViewBag.StatusCode = statusCode;
        ViewBag.OriginalPath = statusCodeReExecuteFeature?.OriginalPath;
        
        return View();
    }
}

Testing

Unit Testing Controllers

// Using xUnit, Moq, and FluentAssertions
public class ProductsControllerTests
{
    [Fact]
    public async Task GetProducts_ReturnsAllProducts()
    {
        // Arrange
        var mockRepo = new Mock<IProductRepository>();
        mockRepo.Setup(repo => repo.GetAllAsync())
            .ReturnsAsync(GetTestProducts());
            
        var controller = new ProductsController(mockRepo.Object);
        
        // Act
        var result = await controller.GetProducts();
        
        // Assert
        var actionResult = Assert.IsType<ActionResult<IEnumerable<Product>>>(result);
        var returnValue = Assert.IsType<OkObjectResult>(actionResult.Result);
        var products = Assert.IsType<List<Product>>(returnValue.Value);
        Assert.Equal(3, products.Count);
    }
    
    private List<Product> GetTestProducts()
    {
        return new List<Product>
        {
            new Product { Id = 1, Name = "Test Product 1" },
            new Product { Id = 2, Name = "Test Product 2" },
            new Product { Id = 3, Name = "Test Product 3" }
        };
    }
}

Integration Testing

// WebApplicationFactory-based testing
public class ProductsApiIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    
    public ProductsApiIntegrationTests(WebApplicationFactory<Program> factory)
    {
        _factory = factory.WithWebHostBuilder(builder =>
        {
            builder.ConfigureServices(services =>
            {
                // Remove the app's ApplicationDbContext registration
                var descriptor = services.SingleOrDefault(
                    d => d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>));
                
                if (descriptor != null)
                {
                    services.Remove(descriptor);
                }
                
                // Add ApplicationDbContext using an in-memory database
                services.AddDbContext<ApplicationDbContext>(options =>
                {
                    options.UseInMemoryDatabase("InMemoryDbForTesting");
                });
                
                // Seed test data
                var sp = services.BuildServiceProvider();
                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var db = scopedServices.GetRequiredService<ApplicationDbContext>();
                    
                    db.Database.EnsureCreated();
                    
                    // Seed the database
                    if (!db.Products.Any())
                    {
                        db.Products.AddRange(
                            new Product { Id = 1, Name = "Test Product 1", Price = 9.99m },
                            new Product { Id = 2, Name = "Test Product 2", Price = 19.99m }
                        );
                        db.SaveChanges();
                    }
                }
            });
        });
    }
    
    [Fact]
    public async Task GetProducts_ReturnsSuccessAndProducts()
    {
        // Arrange
        var client = _factory.CreateClient();
        
        // Act
        var response = await client.GetAsync("/api/products");
        
        // Assert
        response.EnsureSuccessStatusCode();
        var content = await response.Content.ReadAsStringAsync();
        var products = JsonSerializer.Deserialize<List<Product>>(content, 
            new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
            
        Assert.Equal(2, products.Count);
        Assert.Contains(products, p => p.Name == "Test Product 1");
        Assert.Contains(products, p => p.Name == "Test Product 2");
    }
}

Performance Optimization

Response Caching

// Add service
builder.Services.AddResponseCaching();

// Configure middleware
app.UseResponseCaching();

// Use in controller/endpoint
[HttpGet]
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any)]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
    return await _context.Products.ToListAsync();
}

Output Caching (Newer API)

// Add service
builder.Services.AddOutputCache(options =>
{
    // Configure default policy
    options.AddBasePolicy(builder => builder.Expire(TimeSpan.FromMinutes(5)));
    
    // Add named policies
    options.AddPolicy("ShortLived", builder => 
        builder.Expire(TimeSpan.FromSeconds(10))
               .SetVaryByQuery("page", "pageSize"));
});

// Use middleware
app.UseOutputCache();

// Use in controller/endpoint
[HttpGet]
[OutputCache(PolicyName = "ShortLived")]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts(
    [FromQuery] int page = 1, 
    [FromQuery] int pageSize = 10)
{
    // Implementation
}

Memory Caching

// Add service
builder.Services.AddMemoryCache();

// Use in service
public class CachedProductService
{
    private readonly IMemoryCache _cache;
    private readonly ApplicationDbContext _context;
    
    public CachedProductService(IMemoryCache cache, ApplicationDbContext context)
    {
        _cache = cache;
        _context = context;
    }
    
    public async Task<List<Product>> GetProductsAsync()
    {
        // Check if data exists in cache
        if (!_cache.TryGetValue("AllProducts", out List<Product> products))
        {
            // If not in cache, get from database
            products = await _context.Products.ToListAsync();
            
            // Save to cache with expiration
            var cacheOptions = new MemoryCacheEntryOptions()
                .SetAbsoluteExpiration(TimeSpan.FromMinutes(10))
                .SetSlidingExpiration(TimeSpan.FromMinutes(2));
                
            _cache.Set("AllProducts", products, cacheOptions);
        }
        
        return products;
    }
}

Common Challenges and Solutions

Cross-Origin Resource Sharing (CORS)

// Add service with policy
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowSpecificOrigin", builder =>
    {
        builder.WithOrigins("https://example.com")
               .AllowAnyMethod()
               .AllowAnyHeader()
               .AllowCredentials();
    });
    
    options.AddPolicy("AllowAnyOrigin", builder =>
    {
        builder.AllowAnyOrigin()
               .AllowAnyMethod()
               .AllowAnyHeader();
    });
});

// Use middleware
app.UseCors("AllowSpecificOrigin");

// Or apply to specific controllers/endpoints
[EnableCors("AllowAnyOrigin")]
[Route("api/[controller]")]
public class PublicApiController : ControllerBase
{
    // Implementation
}

Handling Long-Running Operations

// Add background service
public class ProcessingService : BackgroundService
{
    private readonly ILogger<ProcessingService> _logger;
    
    public ProcessingService(ILogger<ProcessingService> logger)
    {
        _logger = logger;
    }
    
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Processing Service is starting.");
        
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Processing items...");
            
            // Process work items
            
            await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
        }
        
        _logger.LogInformation("Processing Service is stopping.");
    }
}

// Register service
builder.Services.AddHostedService<ProcessingService>();

Localization and Globalization

// Add services
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

builder.Services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
    
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("fr"),
        new CultureInfo("es")
    };
    
    options.DefaultRequestCulture = new RequestCulture("en-US");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
});

// Use middleware
app.UseRequestLocalization();

// In controller
public class HomeController : Controller
{
    private readonly IStringLocalizer<HomeController> _localizer;
    
    public HomeController(IStringLocalizer<HomeController> localizer)
    {
        _localizer = localizer;
    }
    
    public IActionResult Index()
    {
        ViewData["Welcome"] = _localizer["WelcomeMessage"];
        return View();
    }
}

Best Practices

Security Best Practices

  1. Use HTTPS: Enable HTTPS in development and production
  2. Input Validation: Validate all user inputs with model validation
  3. Output Encoding: Use built-in features like @Html.Raw sparingly
  4. Anti-forgery Tokens: Use @Html.AntiForgeryToken() for forms
  5. Authorization Policies: Implement granular authorization with policies
  6. Secure Configuration: Store secrets in User Secrets or Key Vault
  7. Data Protection API: Use for cookie protection and encryption
  8. Regular Updates: Keep dependencies and frameworks updated

Performance Best Practices

  1. Asynchronous Programming: Use async/await for I/O-bound operations
  2. Caching Strategy: Implement appropriate caching for frequently accessed data
  3. Bundling & Minification: Optimize static assets for production
  4. Efficient Queries: Use specific queries and avoid N+1 query problems
  5. Lazy Loading: Configure Entity Framework appropriately
  6. Response Compression: Enable for appropriate content types
  7. Health Checks: Implement to monitor application health
  8. Use Minimal APIs: For simple CRUD operations when appropriate

Deployment Best Practices

  1. Environment Configuration: Use environment-specific settings
  2. Containerization: Use Docker for consistent deployments
  3. CI/CD Pipeline: Automate build, test, and deployment processes
  4. Logging & Monitoring: Implement comprehensive logging and monitoring
  5. Database Migrations: Use EF Core migrations for database updates
  6. Load Balancing: Deploy behind load balancer for high availability
  7. Backup Strategy: Implement regular database backups
  8. Rollback Plan: Have a strategy for rolling back problematic deployments

Resources for Further Learning

Official Documentation

Community Resources

Recommended Books

  • “ASP.NET Core in Action” by Andrew Lock
  • “Pro ASP.NET Core 6” by Adam Freeman
  • “Microservices with ASP.NET Core” by Christian Horsdal
  • “Entity Framework Core in Action” by Jon P. Smith

This cheat sheet provides a comprehensive reference for ASP.NET Core development. For the most current features and practices, always refer to the official documentation as the framework continues to evolve.

Scroll to Top