Cấu hình IOptions trong ASP.NET Core

Là nhà phát triển phần mềm, chúng ta chắc chắn yêu thích một số tùy chọn, đặc biệt là khi nó cho phép chúng ta thay đổi hành vi ứng dụng mà không cần triển khai lại hoặc biên dịch ứng dụng của chúng ta.

Các vị thần đã khắc sâu cấu hình vào DNA của nhà phát triển. Cho dù bạn là người mới hay cũ đối với ASP.NET, bạn có thể sẽ muốn tận dụng các thiết lập cấu hình bắt nguồn từ tập tin json.

Trong bài viết này, chúng ta sẽ khám phá các bước cần thiết cần thiết để đọc cài đặt cấu hình từ đĩa để làm việc với các giá trị đó.

Lịch sử cấu hình ASP.NET

Đối với những người kỳ cựu trong hệ sinh thái ASP.NET, bạn có thể nhớ tập tin web.config này. Mặc dù không bị bỏ rơi hoàn toàn, nhưng nó đóng một vai trò ít quan trọng hơn trong các ứng dụng ASP.NET Core.

Trong ngữ cảnh của ASP.NET “cổ điển”, tập tin web.config là một tập tin XML nhằm cấu hình môi trường máy chủ của dịch vụ thông tin internet (IIS). Trong tập tin này, chúng ta có thể đặt cài đặt ứng dụng, tải các module web bổ sung, đăng ký trình xử lý và hơn thế nữa. Nói tập tin này đáng sợ cũng không quá.

Một hạn chế khác của cách tiếp cận web.config là thay đổi nội dung tập tin sẽ buộc ứng dụng phải khởi động lại. Các thay đổi có thể đơn giản như thêm cài đặt ứng dụng mới hoặc phức tạp như thêm module mới vào đường dẫn yêu cầu.

Các ứng dụng ASP.NET đã phải tải lại để đảm bảo tính nhất quán logic. Các nhà phát triển có thể khắc phục hạn chế này bằng cách di chuyển tất cả các cài đặt ra bên ngoài phương thức truy cập ConfigurationManager truyền thống và phát triển các giải pháp cài đặt tùy chỉnh.

Thành thật mà nói, theo thời gian, các nhà phát triển coi việc khởi động lại là một tính năng nhiều hơn là một trở ngại, sử dụng nó để thiết lập lại ứng dụng có thể đã rơi vào trạng thái lỗi.

Cấu hình ASP.NET Core

ASP.NET Core đã nhìn thấy các vấn đề chính xung quanh cấu hình và cố gắng cải thiện câu chuyện cho các nhà phát triển xung quanh ba điểm trung tâm:

  • Hỗ trợ cho một nhóm nhà cung cấp cấu hình không giới hạn về mặt lý thuyết ngoài XML.
  • Thay thế singleton ConfigurationManager bằng cách tiếp cận thân thiện với dependency injection (DI).
  • Các thay đổi nóng đối với cài đặt có thể xảy ra ngay lập tức trong các giá trị truy cập mã.

Những thay đổi này phản ánh cách cài đặt hiện đại hơn và thân thiện hơn với các ứng dụng web gốc đám mây. Cài đặt ứng dụng có thể đến từ một số địa điểm và việc cung cấp các tùy chọn và khả năng mở rộng giúp các nhà phát triển dễ dàng tránh các giải pháp tùy chỉnh.

Với việc .NET áp dụng async/await và lập trình không đồng bộ, việc sử dụng singleton có thể dẫn đến bế tắc và chi phí hiệu suất. Việc sao lưu DI vào cấu hình cung cấp cho các nhà phát triển nhiều tùy chọn hơn để sử dụng các cài đặt phụ thuộc và tách các bit dữ liệu này khỏi bất kỳ nguồn duy nhất nào. Nó cũng thực hiện thử nghiệm cài đặt cấu hình mà không cần truy cập ConfigurationManager hoặc web.config.

Khởi động lại là kẻ thù của người dùng ở khắp mọi nơi, tạo ra trải nghiệm khó chịu. Khả năng thực hiện thay đổi mà không cần khởi động lại đảm bảo trải nghiệm thời gian chạy nhất quán hơn.

Làm việc với mã

Vì vậy, chúng ta đã nói về lịch sử và trạng thái hiện tại của cấu hình, nhưng bây giờ chúng ta hãy bắt đầu thực sự sử dụng cài đặt trong ứng dụng ASP.NET Core.

Bước đầu tiên là tạo một lớp dữ liệu sẽ đọc cài đặt từ các nhà cung cấp cấu hình của chúng ta. ASP.NET Core cung cấp nhiều cách khác nhau, nhưng cách thường được sử dụng nhất là sử dụng trình cung cấp cấu hình JSON. Lớp cần có cấu trúc giống như một phần cấu hình của tập tin cấu hình JSON.

public class HelloWorldOptions
{
    public string Text { get; set; }
}

Phần tiếp theo là nói cho ASP.NET Core có thể tìm thấy dữ liệu cho lớp HelloWorldOptions. Chúng ta có thể làm điều này bằng cách sử dụng phương thức BindConfiguration.

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddOptions<HelloWorldOptions>()
        .BindConfiguration("HelloWorld");
}

Chuỗi HelloWorld cho biết phần cấu hình trong tập tin appsettings.json của chúng ta.

{
  "HelloWorld" : {
    "Text": "Hello, Trung Nguyen!"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Tuyệt vời, bây giờ chúng ta đã sẵn sàng sử dụng cấu hình của mình. Đây là nơi mà nó có một chút khó hiểu. Chúng ta có ba interface để lựa chọn:

  • IOptions<T>
  • IOptionsSnapshot<T>
  • IOptionsMonitor<T>

Mỗi interface này bao bọc dữ liệu cấu hình của chúng ta và cung cấp cho chúng ta một dịch vụ có lifetime hơi khác nhau.

Thể hiện của interface IOptions<T> được đăng ký như một singleton, và do đó tất cả các giá trị được truy xuất một lần và được lưu trữ trong bộ nhớ của ứng dụng ASP.NET Core.

Cách tiếp cận này không thể đọc bất kỳ cấu hình cập nhật nào sau khi ứng dụng đã khởi động. Đăng ký như một singleton có nghĩa là ASP.NET có thể đưa interface vào bất kỳ phụ thuộc nào mà không sợ bị bắt hoặc gây ra các vấn đề rò rỉ bộ nhớ. Phiên bản này có thể là thứ mà hầu hết mọi người sẽ sử dụng.

Thể hiện của interface IOptionsSnapshot<T> có thời gian tồn tại là Scoped. ASP.NET Core sẽ tính toán lại một lần cho mỗi yêu cầu HTTP. Lưu vào bộ nhớ đệm thể hiện cho mỗi yêu cầu đảm bảo tính nhất quán cho đến khi người dùng nhận được phản hồi.

Cách tiếp cận ảnh chụp nhanh rất hữu ích cho những người muốn thay đổi hành vi một cách nhanh chóng nhưng vẫn cần các yêu cầu liên tục gửi qua đường ống hiện tại. Phiên bản này hữu ích để sử dụng với các cờ tính năng hoặc hành vi chuyển đổi mà không cần tải lại ứng dụng.

Cuối cùng, thể hiện của interface IOptionsMonitor<T> cũng tương tự như IOptionsSnapshot<T> nhưng có thời gian tồn tại là Singleton. Phương pháp giám sát rất hữu ích cho những thay đổi dữ liệu quan trọng cần được phản ánh ngay lập tức hoặc khi IOptionsMonitor<T> được đặt trong một Singleton khác.

Các dịch vụ nền tồn tại lâu có thể muốn sử dụng thể hiện của IOptionsMonitor để tiếp tục nhận các thay đổi cài đặt nhưng không phải trả chi phí tạo đối tượng đắt đỏ.

Tuyệt vời! Bây giờ chúng ta biết những điểm mạnh của mỗi loại interface, chúng ta có thể sử dụng các cài đặt của mình. Trong phương thức Configure được tìm thấy trong lớp Startup, hãy thêm một điểm cuối GET mới.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            var options = 
                context
                    .RequestServices
                    .GetRequiredService<IOptionsSnapshot<HelloWorldOptions>>()
                    .Value;
            
            await context.Response.WriteAsync(options.Text);
        });
    });
}

Lưu ý rằng trong điểm cuối chúng ta đang sử dụng IOptionsSnapshot. Việc sử dụng thể hiện của IOptionsSnapshot sẽ cho phép chúng ta cập nhật cấu hình của mình mà không cần phải khởi động lại ứng dụng của mình. Khởi động ứng dụng, chúng ta sẽ thấy kết quả sau.

Hello, Trung Nguyen!

Thay đổi cấu hình sẽ thay đổi kết quả của yêu cầu của chúng ta.

{
  "HelloWorld" : {
    "Text": "Hello, World!"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Tải lại trang và đây là kết quả mà chúng ta thấy.

Hello, World!

Wow! Nó đã hoạt động và chúng ta không phải trả chi phí khởi động cho một thay đổi nhỏ trong cài đặt của mình.

Phần kết luận

Lúc đầu, nó có thể gây nhầm lẫn khi sử dụng cấu hình trong ASP.NET Core. Tài liệu của Microsoft có giải thích cặn kẽ về các interface tùy chọn.

Trong hầu hết các trường hợp, mọi người nên sử dụng IOptions<T> vì nó có khả năng hoạt động tốt nhất do được đăng ký vòng đời là Singleton và không hỗ trợ tải lại.

Nếu chúng ta muốn khả năng tải lại nóng các cài đặt, sử dụng IOptionsSnapshot là lựa chọn tốt nhất.

Cuối cùng, nếu ứng dụng của bạn phụ thuộc nhiều vào vòng đời Singleton và vẫn cần cài đặt tải lại nóng, hãy cân nhắc sử dụng IOptionsMonitor.

Tôi hy vọng bạn thấy bài viết này hưu ích với bạn và vui lòng để lại nhận xét về một trong những interface mà bạn chủ yếu sử dụng trong các ứng dụng của mình.

Nếu Comdy hữu ích và giúp bạn tiết kiệm thời gian làm việc

Bạn có thể vui lòng đưa Comdy vào whitelist của trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi trong việc trả tiền cho dịch vụ lưu trữ web để duy trì hoạt động của trang web.

ASP.NET CoreASP.NET Core MVCASP.NET Core Web API
Bài Viết Liên Quan:
Xử lý ngoại lệ với Exception Handler Middleware trong ASP.NET Core
Trung Nguyen 04/11/2021
Xử lý ngoại lệ với Exception Handler Middleware trong ASP.NET Core

Bài viết này sẽ chỉ ra cho chúng ta hai cách sử dụng middleware ExceptionHandlerMiddleware để xử lý các ngoại lệ toàn cục trong ASP.NET Core.