# ASP.NET Core Startup Class Structure Explained: A Complete Guide to dotnet/aspnetcore

> Understand the ASP.NET Core Startup class structure. Learn about the constructor, ConfigureServices, and Configure methods for robust application setup and DI.

- Repository: [.NET Platform/aspnetcore](https://github.com/dotnet/aspnetcore)
- Tags: deep-dive
- Published: 2026-07-13

---

**The ASP.NET Core Startup class consists of three essential parts—an optional constructor for dependency injection, a `ConfigureServices` method to register application services with the DI container, and a `Configure` method to build the HTTP request pipeline.**

The Startup class serves as the central entry point that wires up an application’s services and request-processing pipeline in ASP.NET Core. According to the dotnet/aspnetcore source code, this architectural pattern separates service registration (application-wide) from request pipeline configuration (per-request), making applications composable and testable. Understanding the Startup class structure is essential for configuring middleware, dependency injection, and hosting options across different deployment scenarios.

## The Three Core Components of an ASP.NET Core Startup Class

### Constructor Injection (Optional)

The constructor accepts injected services such as **`IConfiguration`** or **`IWebHostEnvironment`** that are needed during startup. In [`src/Servers/Kestrel/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/samples/SampleApp/Startup.cs), the host injects these dependencies before calling the configuration methods, allowing conditional logic based on configuration settings or environment name.

### ConfigureServices Method

This method registers services with the built-in DI container and runs **once** before any requests are processed. The canonical signature is:

```csharp
public void ConfigureServices(IServiceCollection services)

```

As shown in [`src/DefaultBuilder/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/samples/SampleApp/Startup.cs), this is where you add MVC, Entity Framework Core, authentication, and other framework services. Advanced scenarios in [`src/Hosting/test/testassets/IStartupInjectionAssemblyName/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Hosting/test/testassets/IStartupInjectionAssemblyName/Startup.cs) demonstrate returning a custom **`IServiceProvider`** to replace the default container.

### Configure Method

This method builds the HTTP request pipeline by adding middleware and executes to process requests. The common signature accepts `IApplicationBuilder` and additional services:

```csharp
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)

```

The implementation in [`src/Servers/Kestrel/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/samples/SampleApp/Startup.cs) demonstrates how middleware like `UseClientCertBuffering()` is added to the pipeline. The `IApplicationBuilder` supplied is backed by the built service provider, allowing middleware to request services via `app.ApplicationServices`.

## How the Host Invokes the Startup Class

The generic host processes the Startup class through four distinct phases:

1. **Host creation** – `HostBuilder` (or `WebHostBuilder`) calls `UseStartup<Startup>()` to specify the startup type.
2. **Instance creation** – The host instantiates the Startup class, injecting any constructor parameters it can resolve from the service provider.
3. **Service registration** – `ConfigureServices` is invoked; all services added to `IServiceCollection` become available for constructor injection throughout the application.
4. **Pipeline building** – After the service container is built, `Configure` runs. The `IApplicationBuilder` is backed by the built service provider, enabling middleware to resolve dependencies.

## Implementation Examples from the aspnetcore Repository

### Minimal Configuration (DefaultBuilder Sample)

The minimal implementation in [`src/DefaultBuilder/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/samples/SampleApp/Startup.cs) demonstrates the essential structure with empty service registration and basic request handling:

```csharp
public class Startup
{
    public void ConfigureServices(IServiceCollection services) { }

    public void Configure(IApplicationBuilder app, IConfiguration config)
    {
        app.Run(async ctx =>
        {
            await ctx.Response.WriteAsync($"Hello from {ctx.Request.GetDisplayUrl()}\r\n");
        });
    }
}

```

### MVC and Environment-Specific Middleware

This pattern from the repository demonstrates conditional middleware based on `IWebHostEnvironment` injection:

```csharp
public class Startup
{
    private readonly IWebHostEnvironment _env;

    public Startup(IWebHostEnvironment env) => _env = env;

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
    }

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    {
        if (_env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

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

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

```

### Custom Host Configuration with Kestrel

The full-featured sample in [`src/Servers/Kestrel/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/samples/SampleApp/Startup.cs) includes a static `Main` method and custom Kestrel options:

```csharp
public class Startup
{
    public void ConfigureServices(IServiceCollection services) { }

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    {
        var logger = loggerFactory.CreateLogger("Default");
        app.UseClientCertBuffering();
        app.Run(async context => 
        { 
            // Request handling logic
        });
    }

    public static Task Main(string[] args)
    {
        var host = new HostBuilder()
            .ConfigureWebHost(web =>
            {
                web.UseKestrel((ctx, opts) =>
                {
                    opts.Listen(IPAddress.Loopback, 5000);
                    opts.ListenLocalhost(5001, l => l.UseHttps());
                })
                .UseStartup<Startup>();
            })
            .Build();

        return host.RunAsync();
    }
}

```

Additional reference implementations include HTTP/2 specific configuration in [`src/Servers/Kestrel/samples/Http2SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/samples/Http2SampleApp/Startup.cs), IIS-integrated hosting in [`src/Servers/IIS/IISIntegration/samples/IISSample/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/IIS/IISIntegration/samples/IISSample/Startup.cs), and MVC sandbox examples in [`src/Mvc/samples/MvcSandbox/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/samples/MvcSandbox/Startup.cs).

## Advanced Startup Patterns

### Returning a Custom IServiceProvider

Advanced scenarios may replace the default dependency injection container by returning `IServiceProvider` from `ConfigureServices`. The test asset in [`src/Hosting/test/testassets/IStartupInjectionAssemblyName/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Hosting/test/testassets/IStartupInjectionAssemblyName/Startup.cs) demonstrates this pattern where the method signature becomes `public IServiceProvider ConfigureServices(IServiceCollection services)`.

### Configure Method Overloads

The `Configure` method can accept additional services directly as parameters—such as `IConfiguration`, `ILoggerFactory`, or `IHostEnvironment`—to avoid pulling them manually from the container. This pattern appears throughout the samples including [`src/Servers/Kestrel/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/samples/SampleApp/Startup.cs).

## Summary

- The ASP.NET Core Startup class consists of three logical parts: an optional constructor for dependency injection, `ConfigureServices` for registering application services, and `Configure` for building the middleware pipeline.
- `ConfigureServices` runs once during application startup to populate the DI container, while `Configure` establishes the HTTP pipeline structure that executes per request.
- The dotnet/aspnetcore repository demonstrates variations ranging from minimal startups in [`src/DefaultBuilder/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/samples/SampleApp/Startup.cs) to complex configurations with custom `Main` methods and Kestrel options in [`src/Servers/Kestrel/samples/SampleApp/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/samples/SampleApp/Startup.cs).

## Frequently Asked Questions

### Is the constructor required in an ASP.NET Core Startup class?

No, the constructor is optional. You only need it when your startup logic requires access to injected services like `IConfiguration` or `IWebHostEnvironment` before the configuration methods run. The host can instantiate the Startup class without a constructor if no initial dependencies are required.

### What is the difference between ConfigureServices and Configure in the Startup class?

`ConfigureServices` registers application services with the dependency injection container and runs once at startup to build the service provider, while `Configure` builds the HTTP request pipeline by adding middleware and sets up the application to handle requests. The `IApplicationBuilder` passed to `Configure` is backed by the service provider built from `ConfigureServices`.

### Can I replace the default dependency injection container in the Startup class?

Yes, `ConfigureServices` can return a custom `IServiceProvider` instead of void. This advanced pattern allows you to replace the built-in DI container with alternatives like Autofac or StructureMap, as demonstrated in test assets within the dotnet/aspnetcore repository at [`src/Hosting/test/testassets/IStartupInjectionAssemblyName/Startup.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Hosting/test/testassets/IStartupInjectionAssemblyName/Startup.cs).

### Where does the Configure method get its parameters from?

The host injects parameters into `Configure` from the service provider built after `ConfigureServices` runs. Common parameters include `IApplicationBuilder`, `ILoggerFactory`, `IConfiguration`, and `IWebHostEnvironment`, which are resolved automatically by the generic host without requiring manual lookup from the container.