Dependency Injection in ASP.NET Razor Pages

Dependency Injection (DI) is a fundamental design pattern in modern application development. ASP.NET Core has a built-in, lightweight DI container that makes it easy to implement DI in your Razor Pages applications. This allows for better testability, maintainability, and looser coupling between components.

What is Dependency Injection?

Instead of a class creating its own dependencies (objects it needs to function), those dependencies are "injected" into the class, typically through its constructor. This makes the class less reliant on the concrete implementation of its dependencies, allowing you to swap them out easily, especially for testing.

Configuring Services in Startup.cs

The configuration for your application's services happens in the Startup.cs file (or Program.cs in newer .NET versions, where the configuration is often integrated). You register your services in the ConfigureServices method using the IServiceCollection.

Common Scopes: Transient, Scoped, and Singleton

Example: Registering a Service

Let's say you have a service for retrieving data:


public interface IDataService
{
    IEnumerable<string> GetData();
}

public class MockDataService : IDataService
{
    public IEnumerable<string> GetData()
    {
        return new List<string> { "Data Item 1", "Data Item 2", "Data Item 3" };
    }
}
                

In your Startup.cs (or Program.cs):


// For Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    // Registering MockDataService as a Scoped service
    services.AddScoped<IDataService, MockDataService>();
}

// For Program.cs (minimal API style)
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddScoped<IDataService, MockDataService>();
var app = builder.Build();
// ...
                

Injecting Services into Razor Pages

Once a service is registered, you can inject it into your Razor Page model's constructor. The DI container will automatically resolve and provide the instance when the page is created.

Example: Injecting into a Page Model


using Microsoft.AspNetCore.Mvc.RazorPages;

public class IndexModel : PageModel
{
    private readonly IDataService _dataService;

    public IndexModel(IDataService dataService)
    {
        _dataService = dataService;
    }

    public IEnumerable<string> Items { get; private set; }

    public void OnGet()
    {
        Items = _dataService.GetData();
    }
}
                

Using Injected Services in the Razor View

You can then access the injected data in your Razor view (.cshtml file) through the page model's properties.

Example: Using Data in the View


@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<h1>Welcome to Our Page!</h1>

<p>Here are some items from our data service:</p>

<ul>
    @foreach (var item in Model.Items)
    {
        <li>@item</li>
    }
</ul>
                
Key Takeaway: Dependency Injection in Razor Pages decouples your page logic from specific service implementations, making your code more modular and easier to test.

Advanced Scenarios

By leveraging ASP.NET Core's built-in DI container, you can build robust, scalable, and maintainable Razor Pages applications.