# How Dependency Injection Is Managed in ASP.NET Core Internal Architecture

> Discover how ASP.NET Core manages dependency injection internally using IServiceCollection and IServiceProvider. Learn about WebApplicationBuilder and scoped lifetimes for efficient service management.

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

---

**ASP.NET Core coordinates dependency injection through a centralized `IServiceCollection`/`IServiceProvider` pattern orchestrated by `WebApplicationBuilder`, which leverages an `IServiceProviderFactory` abstraction to construct the root service provider and manages scoped lifetimes per HTTP request.**

The `dotnet/aspnetcore` repository implements dependency injection as a first-class infrastructure concern woven directly into the hosting layer. Understanding how dependency injection is managed in ASP.NET Core internal architecture reveals the extensibility points that allow the framework to support everything from internal singletons to custom third-party containers like Autofac or DryIoc.

## The IServiceCollection and IServiceProvider Foundation

At the heart of the system lies the **Microsoft.Extensions.DependencyInjection** abstractions. The framework uses **`IServiceCollection`** as a mutable registry of service descriptors and **`IServiceProvider`** as the resolved container instance.

In [`src/DefaultBuilder/src/WebApplicationBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/src/WebApplicationBuilder.cs), the `WebApplicationBuilder` initializes a default service collection during construction. User code interacts with this collection through the `builder.Services` property, calling extension methods like `AddControllers()` or `AddAuthentication()` to populate descriptors before the host is built.

Basic registration follows this pattern:

```csharp
var builder = WebApplication.CreateBuilder(args);

// Register application services
builder.Services.AddSingleton<IMySingleton, MySingleton>();
builder.Services.AddScoped<IMyScoped, MyScoped>();
builder.Services.AddTransient<IMyTransient, MyTransient>();

var app = builder.Build();

// Resolve a service manually (usually via constructor injection)
var singleton = app.Services.GetRequiredService<IMySingleton>();

```

## The Host Builder Architecture

### WebApplicationBuilder as the Entry Point

The modern ASP.NET Core stack centers on **`WebApplicationBuilder`**, defined in [`src/DefaultBuilder/src/WebApplicationBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/src/WebApplicationBuilder.cs). This builder aggregates service registrations and configuration into a cohesive host.

When `Build()` is invoked, the builder delegates to the generic host infrastructure to create the concrete service provider. The key abstraction enabling this flexibility is **`IServiceProviderFactory<TBuilder>`**.

### Service Provider Factory Pattern

The host obtains an `IServiceProviderFactory<IServiceCollection>` to transform the collected service descriptors into a functioning `IServiceProvider`. By default, ASP.NET Core uses **`DefaultServiceProviderFactory`**, which ships in the Microsoft.Extensions.DependencyInjection package.

In [`src/DefaultBuilder/src/ConfigureHostBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/src/ConfigureHostBuilder.cs), the `UseServiceProviderFactory<TBuilder>` method allows developers to override this default. This is the extension point that enables third-party containers, as the custom factory receives the populated `IServiceCollection` and returns the root `IServiceProvider` stored in `IHost.Services`.

## Request-Scoped Service Resolution

For each HTTP request, ASP.NET Core creates an **`IServiceScope`** to isolate scoped service instances. This ensures that services registered with `ServiceLifetime.Scoped` (like Entity Framework Core contexts) exist only for the duration of a single request.

When a request arrives at the server, the framework creates a scope from the root provider. Middleware, controllers, and Razor Pages resolve their dependencies from this scoped provider. When the response completes, the framework disposes the scope and all scoped services.

```csharp
app.MapGet("/weather", (IWeatherService weather, IHttpContextAccessor ctx) =>
{
    // `weather` is resolved from the request's scoped provider
    return weather.GetForecast();
});

```

## Component Registration via Extension Methods

Every ASP.NET Core subsystem registers its services through **static extension methods** following the `Add{Feature}` convention. These methods live in `ServiceCollectionExtensions` classes spread across the repository:

- **MVC services** register in [`src/Mvc/Mvc/src/MvcServiceCollectionExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc/src/MvcServiceCollectionExtensions.cs), adding descriptors for `IActionDescriptorCollectionProvider`, `IModelMetadataProvider`, and `IUrlHelperFactory`.
- **Routing services** register in [`src/Http/Routing/src/DependencyInjection/RoutingServiceCollectionExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Http/Routing/src/DependencyInjection/RoutingServiceCollectionExtensions.cs).
- **Authentication services** register in [`src/Security/Authentication/Core/src/AuthenticationServiceCollectionExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Core/src/AuthenticationServiceCollectionExtensions.cs).
- **Health checks** register in [`src/HealthChecks/HealthChecks/src/DependencyInjection/HealthCheckServiceCollectionExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/HealthChecks/HealthChecks/src/DependencyInjection/HealthCheckServiceCollectionExtensions.cs).

Each extension method follows the same pattern:

```csharp
builder.Services.AddControllers();               // registers MVC controllers, filters, model binders, etc.
builder.Services.AddRazorPages();                // registers Razor Pages services
builder.Services.AddMvcCore();                   // low‑level MVC core services

```

All of the above call into [`MvcServiceCollectionExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/MvcServiceCollectionExtensions.cs), which adds dozens of framework services to the same `IServiceCollection`.

## Replacing the Default Container

Developers can replace the built-in DI container by implementing a custom `IServiceProviderFactory<TBuilder>`. In [`src/Hosting/Hosting/src/WebHostBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Hosting/Hosting/src/WebHostBuilder.cs) and related host builder classes, the `UseServiceProviderFactory` extension stores the factory in the host builder properties. When `Build()` executes, the host retrieves this factory and calls `CreateServiceProvider` to produce the container.

Example with Autofac:

```csharp
using Autofac.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// Replace the default provider
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

// Register Autofac modules or direct registrations
builder.Host.ConfigureContainer<ContainerBuilder>(container =>
{
    container.RegisterModule(new MyAutofacModule());
});

var app = builder.Build();

```

## Summary

- **`IServiceCollection`** acts as the mutable registry of service descriptors during startup.
- **`IServiceProviderFactory<IServiceCollection>`** (default: `DefaultServiceProviderFactory`) transforms the collection into a concrete `IServiceProvider`.
- **`WebApplicationBuilder`** in [`src/DefaultBuilder/src/WebApplicationBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/src/WebApplicationBuilder.cs) coordinates registration and defers provider creation to the factory.
- **Scoped services** are isolated per HTTP request via `IServiceScope` instances created by the framework.
- **Extension methods** like `AddMvc()` and `AddAuthentication()` modularize service registration across the repository.
- **Custom containers** integrate via `UseServiceProviderFactory<TBuilder>`, allowing complete replacement of the default DI implementation.

## Frequently Asked Questions

### What is the role of IServiceProviderFactory in ASP.NET Core?

The `IServiceProviderFactory` abstraction decouples the service collection from the concrete container implementation. It receives the populated `IServiceCollection` and returns an `IServiceProvider`, allowing the framework to support the default Microsoft container or third-party alternatives like Autofac without changing consumer code.

### How does ASP.NET Core handle scoped services per request?

The framework creates a new `IServiceScope` from the root provider at the beginning of each HTTP request. All scoped service resolutions during that request share the same scope instance. When the response completes, the framework disposes the scope, triggering disposal of all scoped and transient services created within it.

### Can I replace the built-in DI container with Autofac or DryIoc?

Yes. Call `builder.Host.UseServiceProviderFactory()` with an instance of your preferred container's provider factory (e.g., `AutofacServiceProviderFactory`). This replaces the `DefaultServiceProviderFactory` and allows the custom container to handle all service resolutions for the application lifetime.

### Where are MVC services registered in the ASP.NET Core source?

MVC services register in [`src/Mvc/Mvc/src/MvcServiceCollectionExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc/src/MvcServiceCollectionExtensions.cs) via the `AddMvc()`, `AddControllers()`, and `AddRazorPages()` extension methods. These methods add framework services like `IActionDescriptorCollectionProvider`, `IModelMetadataProvider`, and `IUrlHelperFactory` to the global `IServiceCollection`.