Andrew Lock's .NET Escapades: A Guide to Learning ASP.NET Core Internals
Use Andrew Lock's .NET Escapades blog to learn ASP.NET Core internals: config, hosting, middleware, and DI to grow from intermediate to senior.
If you write ASP.NET Core apps, you have used a lot of magic. You add one line of code, and suddenly logging works. You add another line, and a database connection appears. It feels like the framework reads your mind.
But magic is just code you have not read yet. And there is one person who has read almost all of it for you: Andrew Lock. His blog is called .NET Escapades, and it lives at andrewlock.net. This guide shows you what is on it, why it matters, and how to use it to grow from an intermediate developer into a senior one.
A quick real-life analogy
Imagine you can drive a car. You press the pedal, the car moves. You turn the wheel, it turns. You are a fine driver. But you are not a mechanic.
Now imagine the car breaks down on a quiet road. A driver waits for help. A mechanic opens the hood, looks inside, and fixes it.
Most developers are drivers. They press the pedals of ASP.NET Core and it goes. Andrew Lock's blog turns you into a mechanic. It opens the hood and shows you the engine: how the parts connect, why they are shaped that way, and what happens when you turn the key. When something breaks at 2 a.m., the mechanic is the one who stays calm.
Who is Andrew Lock?
Andrew Lock is a software engineer. He works at Datadog on the .NET tracing library, so he spends his days deep inside how .NET apps actually run. He has been blogging since 2016, and he has written hundreds of posts. He is also the author of the book ASP.NET Core in Action (now in its third edition).
The blog is not a news site. It is a workshop. Each post takes one idea and digs until it hits the source code. He often quotes the real framework code from GitHub and walks through it line by line. That habit is the whole point. You do not just learn what to type. You learn why the framework was built that way.
Why understanding internals matters
You can ship features without knowing internals. So why bother? Here is the honest answer.
| If you only know the surface | If you know the internals |
|---|---|
| You copy config from Stack Overflow and hope | You know which provider wins and why |
| A weird DI error stops you for a day | You read the error and fix it in minutes |
| You guess why middleware order broke a request | You picture the pipeline and reorder it |
| You treat the framework as a black box | You treat it as code you can predict |
Senior engineers are not smarter. They have just seen the inside. When you understand internals, bugs stop being scary. They become puzzles with a known shape. That single shift is what the blog gives you.
The big four topics he covers
The blog covers many things, but four areas are the backbone of ASP.NET Core. Learn these and the rest gets easier.
1. Configuration
Configuration is how your app reads settings: a connection string, an API key, a feature flag. It sounds boring. It is not. Many production bugs are really config bugs in disguise.
Andrew Lock explains the configuration system as layers. Each source (a JSON file, environment variables, command-line args) is stacked. Later sources override earlier ones. When you understand the stack, "why is my setting the wrong value in production?" stops being a mystery.
var builder = WebApplication.CreateBuilder(args);
// Sources are added in order. Later ones win.
// appsettings.json -> appsettings.{Environment}.json
// -> environment variables -> command-line args
string apiKey = builder.Configuration["ApiKey"];He also covers the Options pattern, which binds config into strongly typed classes. His posts on IOptions, IOptionsSnapshot, and IOptionsMonitor explain a question that confuses almost everyone: why are there three of them, and when does each one reload?
// Bind a config section to a typed class.
builder.Services.Configure<EmailSettings>(
builder.Configuration.GetSection("Email"));
// Inject it later. IOptionsMonitor sees live changes.
public class Mailer(IOptionsMonitor<EmailSettings> options)
{
public void Send() => Connect(options.CurrentValue.Host);
}2. Hosting and the generic host
Every modern .NET app, web or not, starts with a host. The host is the thing that wires up configuration, logging, and dependency injection, then starts your app and keeps it alive.
Andrew Lock has a whole series on the generic host. His key point: the generic host is generic. It has nothing to do with HTTP by itself. A console worker, a background service, and a web app all share the same host base. Web stuff is layered on top. Once you see this, the startup code in Program.cs stops looking like a spell and starts looking like a list of steps.
What the host does at startup
Steps
Build config
Stack all settings sources
Set up logging
Register log providers
Build DI container
Register every service
Start services
Run hosted services
Handle requests
Serve HTTP traffic
3. Middleware and the request pipeline
When an HTTP request arrives, it does not jump straight to your code. It walks through a pipeline of middleware. Each piece can look at the request, do something, and pass it on, or stop it cold.
Think of airport security lines. Each desk checks one thing and passes you to the next. If one desk turns you away, you never reach the gate. Middleware order is the order of the desks, and order matters a lot.
var app = builder.Build();
app.UseExceptionHandler(); // first: catches errors below it
app.UseAuthentication(); // who are you?
app.UseAuthorization(); // are you allowed?
app.MapControllers(); // finally: your endpointAndrew Lock's posts show what a middleware really is: a function that takes the next function and returns a new one. His Behind the scenes of minimal APIs series goes even deeper. It shows how a tiny app.MapGet(...) call is turned into a RequestDelegate the pipeline can run. Reading that series changes how you see the whole framework.
4. Dependency injection internals
Dependency injection (DI) is how your classes get the things they need without building them by hand. You ask for an interface in a constructor, and the framework hands you a real object.
Most tutorials stop at "register it and inject it." Andrew Lock goes further. He explains service lifetimes in real depth:
| Lifetime | One instance per | Common use |
|---|---|---|
| Singleton | Whole app | Caches, config, stateless helpers |
| Scoped | One request | DbContext, per-request data |
| Transient | Every injection | Lightweight, cheap services |
He also explains traps that bite real teams. The classic one is a captive dependency: when a singleton holds a scoped service, the scoped one gets frozen for the whole app and never refreshes. His posts on validating the DI container at startup help you catch these before users do.
// Catch lifetime mistakes early, not in production.
var host = builder.Build(); // ValidateScopes throws if a
// singleton captures a scoped serviceHe has also covered why the old Startup class pattern needed the DI container to be built twice, and how the newer minimal hosting model avoids that. These are the details that separate "it works" from "I know why it works."
One more habit worth copying from his DI posts: turn on container validation in development. It costs nothing and catches a whole class of mistakes for you. When the app starts, the container checks that every service can actually be built and that no singleton is holding onto a scoped service. If something is wrong, you get a clear error at startup instead of a strange crash hours later under load. Small switch, big payoff.
// Fail fast at startup instead of failing slowly in production.
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = true; // catch captive dependencies
options.ValidateOnBuild = true; // build every service once
});A suggested reading path
Do not try to read the whole blog at once. There are hundreds of posts. Follow this path instead, in order.
From intermediate to senior, one series at a time
Steps
Generic host
See how an app starts
Configuration
Settings and options
Dependency injection
Lifetimes and traps
Middleware
The request pipeline
Behind the scenes
Read real source code
Exploring .NET 11
Stay current with new releases
- Start with hosting. Read the generic host posts so
Program.csmakes sense. - Then configuration and options. This unlocks half of all "wrong setting" bugs.
- Then dependency injection. Learn lifetimes until they are boring. They will save you.
- Then middleware. Picture the pipeline every time you write
app.Use.... - Then a "Behind the scenes" series. Minimal APIs is a great first one.
- Then the "Exploring" series for the current release to keep up to date.
How this levels you up to senior
A senior developer is trusted with hard, fuzzy problems. The blog builds three habits that earn that trust.
First, you learn to read source code. Andrew Lock models this on every post. He does not just tell you the answer; he shows you where he found it on GitHub. Soon you start doing the same, and the framework stops being scary.
Second, you learn to predict behavior. Once you can picture the host, the pipeline, and the container, you can guess what a change will do before you run it. Seniors are valued for good guesses.
Third, you learn to explain. The posts are written in plain words with small examples. When you copy that style in code reviews and design docs, people understand you, and they follow you. Being clear is a real skill, and the blog is a great teacher of it.
A few notes on staying current
The .NET world keeps moving, and the blog keeps up. As of 2026, .NET 10 is the LTS release, C# 14 has shipped, and C# 15 with union types is in the .NET 11 preview. Andrew Lock runs an "Exploring the .NET 11 preview" series that walks through new features as they land, often with the source code behind them.
One more current-events note worth knowing as you read older posts: some popular libraries that used to be free, like MediatR, MassTransit, and AutoMapper, are now commercially licensed. Older blog posts may still show them as free. That does not make the ideas wrong, but check the license before you add them to a new project.
Quick recap
- Andrew Lock's .NET Escapades (andrewlock.net) is a free blog that opens the hood of ASP.NET Core.
- The big four topics are configuration, hosting, middleware, and dependency injection. Master these first.
- Internals matter because they turn scary bugs into solvable puzzles, which is the core skill of a senior.
- Read in order: host, then config, then DI, then middleware, then a Behind the scenes series.
- His "Exploring" series keeps you current with new releases like the .NET 11 preview.
- The goal is simple: stop being a driver, become a mechanic.
References and further reading
- Andrew Lock | .NET Escapades (home)
- Series: Behind the scenes of minimal APIs
- Series: Exploring ASP.NET Core 3.0 (generic host and more)
- Series: Exploring the .NET 11 preview
- Exploring the new project file, Program.cs, and the generic host
- Avoiding Startup service injection in ASP.NET Core 3
- Microsoft Docs: Dependency injection in ASP.NET Core
- Microsoft Docs: .NET Generic Host