Program.cs
Program.cs is where your app is assembled. It has a clear shape — register services, build, configure the pipeline, map endpoints, run — and once you see that shape every ASP.NET Core project becomes easy to read.
On this page · 5 min · Beginner
On this page
- In simple words
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 29, 2026
Related tutorials
In simple words#
Program.cs is the app’s ignition and dashboard: register what the app needs (services), then set up the route every request travels (middleware), then start the engine.
- builder.Services
- Register services for DI.
- app.Use…
- Add middleware in order.
- app.Run()
- Start listening for requests.
Learning objectives#
- Read the four phases of Program.cs
- Register services on builder.Services
- Configure the pipeline differently per environment
- Map MVC routes and static assets
Explanation#
WebApplication.CreateBuilder(args) creates a builder with sensible defaults: Kestrel, configuration from appsettings.json, environment variables and command-line args, logging to the console, and a dependency injection container.
Phase 1 — services: builder.Services.AddControllersWithViews(), AddDbContext, AddScoped<IMyService, MyService>()… Everything your app needs is registered here, before Build().
Phase 2 — build: var app = builder.Build(); After this, the service list is locked.
Phase 3 — pipeline: app.UseExceptionHandler, UseHsts, UseHttpsRedirection, UseRouting, UseAuthentication, UseAuthorization… Order matters; production-only middleware sits inside if (!app.Environment.IsDevelopment()).
Phase 4 — endpoints and run: MapStaticAssets() serves wwwroot with fingerprinting and caching (.NET 9), MapControllerRoute defines the conventional route, and app.Run() starts listening until the app is stopped.
Syntax#
var builder = WebApplication.CreateBuilder(args); // defaults: Kestrel, config, logging, DI
builder.Services.Add…(); // 1. services
var app = builder.Build(); // 2. build
app.Use…(); // 3. middleware pipeline
app.Map…(); // 4. endpoints
app.Run();
Code example: ShopSmart’s Program.cs#
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// ── 1. Register services ──
builder.Services.AddControllersWithViews();
builder.Services.AddScoped<IProductCatalog, InMemoryProductCatalog>();
// ── 2. Build the app ──
var app = builder.Build();
// ── 3. Configure the HTTP request pipeline ──
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error"); // friendly error page in production
app.UseHsts(); // tell browsers to always use HTTPS
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
// ── 4. Map endpoints and run ──
app.MapStaticAssets(); // wwwroot files, fingerprinted and cached
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.WithStaticAssets();
app.Run();
// Services/IProductCatalog.cs
public interface IProductCatalog
{
IReadOnlyList<string> GetNames();
}
public class InMemoryProductCatalog : IProductCatalog
{
public IReadOnlyList<string> GetNames() => ["Wireless Mouse", "USB-C Hub", "Mechanical Keyboard"];
}
The app starts, prints “Now listening on: https://localhost:7046”, and serves ShopSmart. In Development, errors show the detailed developer exception page; in Production they go to /Home/Error.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- CreateBuilder sets up configuration, logging, Kestrel and DI.
- Services are registered on builder.Services before Build(); IProductCatalog will be injected wherever it is requested.
- The pipeline is configured on app: production-only middleware first, then HTTPS redirection, routing and authorization.
- MapStaticAssets and the default controller route connect URLs to files and controllers.
- app.Run() blocks and serves requests until the process stops.
Real-world use case#
Every feature added to ShopSmart touches Program.cs once: AddDbContext for the database, AddIdentity for logins, AddSession, AddResponseCaching… and the matching Use… call in the right place.
Common mistakes#
builder.Services is read-only after Build(); registering later throws “The service collection cannot be modified because it is read-only”.
UseAuthorization before UseRouting, or UseAuthentication after UseAuthorization, silently breaks security.
Dozens of registrations make it hard to read. Group them in extension methods like builder.Services.AddShopServices().
Best practices#
- Keep the four phases visually separate
- Wrap production-only middleware in an environment check
- Move groups of registrations into extension methods
- Use MapStaticAssets in .NET 9+ for cache-friendly static files
Remember this#
Services → Build → Pipeline → Endpoints → Run.
Register on builder.Services, configure on app.
IsDevelopment() decides error pages and HSTS.
Practice exercise#
Your task: Move the ShopSmart service registrations into an extension method builder.Services.AddShopServices() in a file Extensions/ServiceCollectionExtensions.cs, and call it from Program.cs.
Need a hint?
Show solution
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddShopServices();
var app = builder.Build();
app.MapDefaultControllerRoute();
app.Run();
// Extensions/ServiceCollectionExtensions.cs
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddShopServices(this IServiceCollection services)
{
services.AddScoped<IProductCatalog, InMemoryProductCatalog>();
return services;
}
}
public interface IProductCatalog { IReadOnlyList<string> GetNames(); }
public class InMemoryProductCatalog : IProductCatalog
{
public IReadOnlyList<string> GetNames() => ["Wireless Mouse"];
}
Mini quiz#
Where must services be registered?
Want more? Practise all ASP.NET Core MVC MCQs · ASP.NET Core MVC interview questions
My notes#
Saved in this browser.