Executing code after app.Run in .NET Core
A short note on running code around app.Run() in .NET Core while respecting the application lifecycle.
Some work must happen exactly once when an application starts: warming a cache, reading configuration, testing a database connection, launching a background job. Putting it on every request repeats it needlessly.
The example below solves this with a middleware: a flag is kept inside the class, the work runs on the first request only, and later requests pass straight through. Because the middleware instance lives for the lifetime of the application, the flag persists.
Things to watch
- The first request waits for the startup work, so it is slower than the rest. If the work is long, move it to the background instead of blocking the request.
- Two concurrent requests can read the flag at the same time; if the work must truly run once, you need locking.
- Modern .NET also offers
IHostedServicefor this; the middleware approach fits when the startup work depends on the request pipeline.
First, let us define a middleware class.
public class StartUp
{
private readonly RequestDelegate next;
private bool running = false;
public StartUp(RequestDelegate next)
{
this.next = next;
}
public Task Invoke(HttpContext httpContext)
{
if (!running)
{
//The code we want to run
running = true;
}
return next(httpContext);
}
}
Now let us add this class to our Program.cs file.
The part we add should preferably be right before the app.Run() statement.
app.UseMiddleware
app.Run();
After this operation, our middleware class will be registered in our project and, due to the life cycle of the .NET Core platform, it will be invoked on every request.
The reason we add it last is to avoid trouble accessing definitions that may be created in earlier operations. (There is no special meaning :))
Short guide
When to use it
Running code after app.Run is usually about cleanup, closing logs or ending background work when the service stops. The important point is understanding when that code can actually run.
What to watch
- Understand the application lifecycle and host shutdown behaviour.
- Avoid uncontrolled long-running work during shutdown.
- Use BackgroundService or hosted services when they fit the problem better.
Common mistake
Putting critical work after app.Run and assuming it will always run is unsafe. A crash, forced stop or server interruption can skip it entirely.
A note for long-term fixes
When fixing an error, hiding the message is rarely enough. Version, operating system, dependencies, encoding, server settings and logs should be reviewed together. For a long-term fix, it is better to review the environment, dependencies and data flow together.