Dependency injection (DI) lets a class or endpoint declare the services it needs instead of creating them with `new`. An external container supplies those dependencies. This keeps code focused on its own job and makes it easier to replace an implementation without rewriting its consumer. In ASP.NET Core, DI supports both framework features and application services. section 3.7.1 section 8.3
A service is a class or interface registered with the container. Registration tells the container which implementation to provide—for example, to use `EmailSender` when code requests `IEmailSender`. The container also creates the registered dependencies needed to construct that implementation; together, these objects form a dependency graph. section 8.6 section 9.1
A typical setup has three parts:
- Register services through `builder.Services` in `Program.cs`, before calling `builder.Build()`. Optional framework features often provide an `Add*` method, such as `AddRazorPages()`, that registers their required services together. section 8.4
- Declare a dependency where it is used. A minimal API handler can take a registered service as a parameter; a Razor Page model can receive one through its constructor. The framework obtains the service and passes it in. section 8.5 section 13.2
- Choose a lifetime when registering an application service: transient creates an instance for each request for that service, scoped reuses one within a scope (one per web request in ASP.NET Core), and singleton reuses one across scopes. section 9.4
Replace manual construction in a registration endpoint
A handler that creates `EmailSender`, `MessageFactory`, `NetworkClient`, and email-server settings itself must know how the whole chain is built. Instead, give the handler an `IEmailSender` parameter and call `emailSender.SendEmail(username)`. Register `IEmailSender` as `EmailSender` and register its dependencies so the container can construct the chain. If a required service is missing, the application can fail at runtime; an unregistered minimal API parameter may instead be treated as request-body input. section 9.1
Listing 9.3 Registering services with the DI container
WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Services.AddScoped<IEmailSender, EmailSender>(); #1 builder.Services.AddScoped<NetworkClient>(); #2 builder.Services.AddSingleton<MessageFactory>(); #3 WebApplication app = builder.Build(); app.MapGet("/register/{username}", RegisterUser); app.Run(); string RegisterUser(string username, IEmailSender emailSender) { emailSender.SendEmail(username); return $"Email sent to {username}!"; } #1 Whenever you require an IEmailSender, use EmailSender. #2 Whenever you require a NetworkClient, use NetworkClient. #3 Whenever you require a MessageFactory, use MessageFactory.
The registration example pairs an interface with its implementation, registers two supporting classes, and lets the endpoint request `IEmailSender` directly. The email-server settings used by the full example also need registration. section 9.1
Prefer declared dependencies to fetching services inside handlers. Direct retrieval through `app.Services.GetRequiredService<T>()` is available for work in `Program.cs` outside a request, but using the container as a service locator inside handlers is generally discouraged. Take care with lifetimes, too: a long-lived service capturing a shorter-lived dependency can cause difficult-to-debug behavior. section 8.6 section 9.4
Some integration points need an extra step. C# attributes cannot accept ordinary service dependencies in their constructors, so a filter can put its behavior in a separate class and use `TypeFilterAttribute` or `ServiceFilterAttribute` to obtain it through DI. section 22.3




















