Nguon: Microsoft Learn · .NET 8.0

Dependency Injection vào Controllers trong ASP.NET Core

Nguồn: Dependency injection into controllers in ASP.NET Core

Bởi Rick Anderson

Các controllers trong ASP.NET Core MVC yêu cầu dependencies (phụ thuộc) một cách tường minh qua constructors. ASP.NET Core có hỗ trợ tích hợp cho dependency injection (DI - tiêm phụ thuộc). DI giúp ứng dụng dễ kiểm thử và bảo trì hơn.

Xem hoặc tải xuống mã mẫu

Constructor Injection (Tiêm qua Constructor)

Services (dịch vụ) được thêm vào như tham số constructor, và runtime (môi trường chạy) resolves (giải quyết) service từ service container (vùng chứa dịch vụ). Services thường được định nghĩa qua interfaces (giao diện). Ví dụ, xét ứng dụng cần biết thời gian hiện tại. Interface sau hiển thị service IDateTime:

csharp
public interface IDateTime
{
    DateTime Now { get; }
}

Code sau implement (triển khai) interface IDateTime:

csharp
public class SystemDateTime : IDateTime
{
    public DateTime Now
    {
        get { return DateTime.Now; }
    }
}

Thêm service vào service container:

csharp
public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();

    services.AddControllersWithViews();
}

Xem thêm về AddSingleton tại DI service lifetimes (vòng đời service DI).

Code sau hiển thị lời chào tới người dùng dựa trên thời điểm trong ngày:

csharp
public class HomeController : Controller
{
    private readonly IDateTime _dateTime;

    public HomeController(IDateTime dateTime)
    {
        _dateTime = dateTime;
    }

    public IActionResult Index()
    {
        var serverTime = _dateTime.Now;
        if (serverTime.Hour < 12)
        {
            ViewData["Message"] = "It's morning here - Good Morning!";
        }
        else if (serverTime.Hour < 17)
        {
            ViewData["Message"] = "It's afternoon here - Good Afternoon!";
        }
        else
        {
            ViewData["Message"] = "It's evening here - Good Evening!";
        }
        return View();
    }

Chạy ứng dụng sẽ hiển thị thông điệp dựa trên thời gian.

Action Injection với FromServices

Thuộc tính FromServicesAttribute cho phép tiêm service trực tiếp vào action method mà không cần constructor injection:

csharp
public IActionResult About([FromServices] IDateTime dateTime)
{
    return Content( $"Current server time: {dateTime.Now}");
}

Action Injection với FromKeyedServices

Code sau cho thấy cách truy cập keyed services (dịch vụ có khóa) từ DI container bằng thuộc tính [FromKeyedServices]:

csharp
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();

app.Run();

public interface ICache
{
    object Get(string key);
}
public class BigCache : ICache
{
    public object Get(string key) => $"Resolving {key} from big cache.";
}

public class SmallCache : ICache
{
    public object Get(string key) => $"Resolving {key} from small cache.";
}

[ApiController]
[Route("/cache")]
public class CustomServicesApiController : Controller
{
    [HttpGet("big")]
    public ActionResult<object> GetBigCache([FromKeyedServices("big")] ICache cache)
    {
        return cache.Get("data-mvc");
    }

    [HttpGet("small")]
    public ActionResult<object> GetSmallCache([FromKeyedServices("small")] ICache cache)
    {
        return cache.Get("data-mvc");
    }
}

Truy cập Settings từ Controller

Truy cập settings (cài đặt) của ứng dụng hoặc cấu hình từ trong controller là mẫu phổ biến. Options pattern (mẫu tùy chọn) được mô tả trong Options pattern in ASP.NET Core là cách tiếp cận ưu tiên để quản lý settings. Nhìn chung, không nên tiêm trực tiếp IConfiguration vào controller.

Tạo class đại diện cho các options. Ví dụ:

csharp
public class SampleWebSettings
{
    public string Title { get; set; }
    public int Updates { get; set; }
}

Thêm configuration class vào services collection:

csharp
public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();
    services.Configure<SampleWebSettings>(Configuration);

    services.AddControllersWithViews();
}

Cấu hình ứng dụng đọc settings từ file JSON:

csharp
public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("samplewebsettings.json",
                    optional: false,
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Code sau yêu cầu settings IOptions<SampleWebSettings> từ service container và dùng chúng trong phương thức Index:

csharp
public class SettingsController : Controller
{
    private readonly SampleWebSettings _settings;

    public SettingsController(IOptions<SampleWebSettings> settingsOptions)
    {
        _settings = settingsOptions.Value;
    }

    public IActionResult Index()
    {
        ViewData["Title"] = _settings.Title;
        ViewData["Updates"] = _settings.Updates;
        return View();
    }
}

Controllers as Services (Controllers như là Services)

Theo mặc định, ASP.NET Core không đăng ký controllers là services trong DI container. Runtime dùng DefaultControllerActivator để tạo controller instances và resolve services từ DI container cho các tham số constructor, nhưng bản thân controller không được resolve từ container.

Gọi AddControllersAsServices đăng ký tất cả controllers là services trong DI container:

csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews().AddControllersAsServices();

Đăng ký controllers là services cho phép:

Lưu ý: Cấu hình ApplicationPartManager trước khi gọi AddControllersAsServices. Xem Share controllers, views, Razor Pages and more with Application Parts in ASP.NET Core để biết chi tiết.

Tài nguyên bổ sung