A service is an object managed by ASP.NET Core to provide a feature to other application components. Any class can be a service. Services commonly supply functionality needed in several places, such as logging or database access; middleware and endpoints can use only the services they need. Dependency injection makes those objects available without requiring each component to create them. section 12.2.2 section 14.0
Register services through `builder.Services` in `Program.cs`. For example, `AddControllersWithViews()` sets up objects needed by MVC controllers and Razor views. This configures available services; middleware and endpoint mappings separately determine how requests are processed. section 7.1.5
To define and consume an application service:
- Choose the feature to share. An interface can hide its implementation, but a concrete class can also be a service. section 9.1
- Register its type, an existing object, or a factory function. Choose a lifetime to control when instances are created and shared. section 14.6
- Declare a dependency where it is needed, such as a constructor parameter on a Razor Page model. ASP.NET Core supplies the service through dependency injection. section 9.1.3 section 14.6
Keep cart persistence out of the page
When a cart page loads and stores its own session data, every other page or controller using the cart risks duplicating that work. Making `Cart` available as a service lets the page model request `Cart cartService` in its constructor and leave creation and persistence details elsewhere. A unit test can then construct the page model with a test cart and mock repository, without obtaining the cart through context objects. section 9.1 section 9.1.3
Service registration can also depend on the environment. Before `builder.Build()`, `builder.Environment` is available even though services cannot normally be resolved yet. An `IsDevelopment()` check can therefore register different implementations of an interface for development and other environments. section 14.5.2
Listing 14.33 Accessing configuration data in the Program.cs file in the Platform folder
using Platform;
using Platform.Services;
var builder = WebApplication.CreateBuilder(args);
IWebHostEnvironment env = builder.Environment;
if (env.IsDevelopment()) {
builder.Services.AddScoped<IResponseFormatter,
TimeResponseFormatter>();
builder.Services.AddScoped<ITimeStamper, DefaultTimeStamper>();
} else {
builder.Services.AddScoped<IResponseFormatter,
HtmlResponseFormatter>();
}
var app = builder.Build();
app.UseMiddleware<WeatherMiddleware>();
app.MapEndpoint<WeatherEndpoint>("endpoint/class");
app.MapGet("endpoint/function",
async (HttpContext context, IResponseFormatter formatter) => {
await formatter.Format(context,
"Endpoint Function: It is sunny in LA");
});
app.Run();
The `Program.cs` listing registers scoped formatter implementations according to the environment, then requests a formatter in an endpoint handler. section 14.5.2
