Tổng quan về các nền tảng trong ASP.NET Core

2022-07-30 21:48:11 | khoảng 15 phút đọc

Xin chào các bạn, mình là Huy, một developer. Bài tiếp theo trong series này mình sẽ nói về tổng quan các thuật ngữ, nền tảng cơ bản mà framework ASP.NET Core sử dụng bao gồm dependency injection (DI), cấu hình, middleware, và nhiều hơn thế nữa.

Program.cs

Những ứng dụng ASP.NET Core được tạo với web template sẽ chứa code khởi động ứng dụng trong file Program.cs. File này là nơi:

  • Cấu hình các service được yêu cầu bởi ứng dụng.
  • Định nghĩa luồng xử lý request của ứng dụng dưới dạng một chuỗi các thành phần middleware.

Đoạn code khởi động bên dưới hỗ trợ:

  • Razor Pages
  • Bộ điều khiển MVC với view
  • Web API với controller
  • Minimal Web API
var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
 
var app = builder.Build();
 
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
 
app.UseHttpsRedirection();
app.UseStaticFiles();
 
app.UseAuthorization();
 
app.MapGet("/hi", () => "Hello!");
 
app.MapDefaultControllerRoute();
app.MapRazorPages();
 
app.Run();

Dependency injection

Nếu bạn nào đã từng tiếp xúc với Laravel thì có thể đã nghe đến thuật ngữ này rồi. ASP.NET Core sử dụng denpendency injection (DI) để cung cấp các service đã được cấu hình cho toàn bộ ứng dụng. Các service có thể được thêm vào DI container với WebApplicationBuilder.Services, chính là builder.Services ở đoạn code trên. Khi WebApplicationBuilder được khởi tạo, các service do framework cung cấp sẽ được thêm vào, builder là một WebApplicationBuilder như đoạn code bên dưới:

var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
 
var app = builder.Build();

Trong đoạn code trên, builder có cấu hình, logging, và nhiều service khác được thêm vào DI container.

Đoạn code bên dưới đây ví dụ cho việc thêm Razor Pages, bộ điều khiển MVC với view và một DbContext tùy chỉnh trong DI Container.

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
 
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("RPMovieContext")));
 
var app = builder.Build();

Các service thường được resolve từ DI sử dụng constructor injection. DI cung cấp một khởi tạo của service trong thời gian chạy.

Đoạn code bên dưới đây sử dụng constructor injection để resolve database context và logger từ DI:

public class IndexModel : PageModel
{
private readonly RazorPagesMovieContext _context;
private readonly ILogger<IndexModel> _logger;
 
public IndexModel(RazorPagesMovieContext context, ILogger<IndexModel> logger)
{
_context = context;
_logger = logger;
}
 
public IList<Movie> Movie { get;set; }
 
public async Task OnGetAsync()
{
_logger.LogInformation("IndexModel OnGetAsync.");
Movie = await _context.Movie.ToListAsync();
}
}

Middleware

Luồng xử lý request được bao gồm một loạt các thành phần middleware, mỗi thành phần thực hiện những câu lệnh dựa trên HttpContext hoặc gọi middleware kế tiếp hoặc kết thúc request.

Theo quy ước, một thành phần middleware được thêm vào luồng bằng cách gọi một extension method Use{Feature}. Middleware được thêm vào ứng dụng được highlight ở đoạn code bên dưới:

var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
 
var app = builder.Build();
 
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
 
app.UseHttpsRedirection();
app.UseStaticFiles();
 
app.UseAuthorization();
 
app.MapGet("/hi", () => "Hello!");
 
app.MapDefaultControllerRoute();
app.MapRazorPages();
 
app.Run();

Host

Khi khởi động, một ứng dụng ASP.NET Core sẽ xây dựng một host, host đóng gói tất cả tài nguyên của ứng dụng, chẳng hạn:

  • Một triển khai HTTP server
  • Các thành phần middleware
  • Logging
  • Các DI service
  • Cấu hình

Có ba loại host khác nhau:

  • .NET WebApplication Host, được biết đến là Minimal Host.
  • .NET Generic Host
  • ASP.NET Core Web Host

.NET WebApplication Host được khuyến nghị và sử dụng cho tất cả các ASP.NET Core template. .NET WebApplication Host và .NET Generic Host chia sẻ nhiều interface và class giống nhau. ASP.NET Core Web Host chỉ có sẵn khả năng tương thích ngược1.

Đoạn code bên dưới khởi tạo một WebApplication Host:

var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
 
var app = builder.Build();

Method WebApplicationBuilder.Build cấu hình một host với tập hợp các tùy chọn mặc định như là:

  • Sử dụng Kestrel như là một web server và cho phép tích hợp IIS.
  • Tải cấu hình từ file appsettings.json, các biến môi trường, đối số dòng lệnh, và các nguồn cấu hình khác.
  • Gửi đầu ra logging đến console và các debug provider.

Các tình huống không phải là web

Generic Host cho phép các loại ứng dụng khác sử dụng các tiện ích cross-cutting trong framework như logging, DI, cấu hình, và trình quản lý thời gian sống của ứng dụng.

Máy chủ

Một ứng dụng ASP.NET Core sử dụng một triển khai HTTP server để lắng nghe các HTTP request. Máy chủ hiển thị các request đến ứng dụng dưới dạng một tập hợp các request features tạo thành HttpContext.

Windows

ASP.NET Core cung cấp các triển khai máy chủ như bên dưới:

  • Kestrel là một cross-platform web server. Kestrel thường được chạy trong một cấu hình proxy ngược bằng cách sử dụng IIS. Trong ASP.NET Core 2.0 trở đi. Kestrel có thể chạy như một máy chủ biên công khai tiếp xúc trực tiếp với Internet.
  • IIS HTTP Server là một máy chủ cho Windows sử dụng IIS. Với máy chủ này, ứng dụng ASP.NET Core và IIS có thể chạy trong cùng một tiến trình.
  • HTTP.sys là một máy chủ cho Windows nhưng không sử dụng IIS.

macOS và Linux

ASP.NET Core cung cấp triển khai máy chủ Kestrel cho hai hệ điều hành này.

Cấu hình

ASP.NET cung cấp một khung cấu hình để lấy các thiết lập dưới dạng cặp name-value từ tập hợp trình cấu hình được sắp xếp theo thứ tự. Các trình cấu hình tích hợp sẵn có sẵn nhiều nguồn khác nhau, như file .json, file .xml, các biến môi trường và các đối số dòng lệnh. Tự viết trình cấu hình tùy chỉnh có thể hỗ trợ nhiều nguồn khác.

Mặc định, ứng dụng ASP.NET Core được cấu hình thông qua đọc file appsettings.json, biến môi trường, đối số dòng lệnh... Khi cấu hình được tải, giá trị của biến môi trường sẽ ghi đè giá trị từ file appsettings.json.

Để quản lý các dữ liệu cấu hình bí mật như mật khẩu, .NET Core cung cấp Secret Manager. Ở chế độ production, Microsoft khuyến khích chúng ta sử dụng Azure Key Vault.

Môi trường

ASP.NET Core có sẵn các môi trường như Development, Stagging, Production. Ta có thể chỉ định môi trường cho ứng dụng đang chạy bằng các thiếp lập biến môi trường ASPNETCORE_ENVIRONMENT. ASP.NET Core sẽ đọc biến môi trường tại lúc khởi động ứng dụng và lưu trữ giá trị trong một triển khai IWebHostEnvironment. Triển khai này luôn có sẵn trong một ứng dụng thông qua DI.

var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
 
var app = builder.Build();
 
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
 
app.UseHttpsRedirection();
app.UseStaticFiles();
 
app.UseAuthorization();
 
app.MapGet("/hi", () => "Hello!");
 
app.MapDefaultControllerRoute();
app.MapRazorPages();
 
app.Run();

Logging

ASP.NET Core hỗ trợ một logging API làm việc với nhiều loại tích hợp sẵn và trình logging bên thứ ba. Các trình logging có sẵn bao gồm:

  • Console
  • Debug
  • Event Tracing on Windows.
  • Windows Event Log
  • TraceSource
  • Azure App Service
  • Azure Application Insights

Để tạo log, resolve một service ILogger<TCategoryName> từ DI và gọi các phương thức logging như LogInformation. Ví dụ:

public class IndexModel : PageModel
{
private readonly RazorPagesMovieContext _context;
private readonly ILogger<IndexModel> _logger;
 
public IndexModel(RazorPagesMovieContext context, ILogger<IndexModel> logger)
{
_context = context;
_logger = logger;
}
 
public IList<Movie> Movie { get;set; }
 
public async Task OnGetAsync()
{
_logger.LogInformation("IndexModel OnGetAsync.");
Movie = await _context.Movie.ToListAsync();
}
}

Routing

Một route là một mẫu URL được ánh xạ đến một trình xử lý. Trình xử lý này thường là một Razor page, một action method trong MVC controller, hoặc một middleware. ASP.NET Core routing cho phép ta kiểm soát các URL được sử dụng bởi ứng dụng.

Đoạn code bên dưới được tạo bởi mẫu ASP.NET Core web application có sử dụng UseRouting:

var builder = WebApplication.CreateBuilder(args);
 
builder.Services.AddRazorPages();
 
var app = builder.Build();
 
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
 
app.UseHttpsRedirection();
app.UseStaticFiles();
 
app.UseRouting();
 
app.UseAuthorization();
 
app.MapRazorPages();
 
app.Run();

Trình xử lý lỗi

ASP.NET Core có các tính năng tích hợp sẵn cho việc xử lý lỗi, chẳng hạn:

  • Một trang ngoại lệ dành cho nhà phát triển
  • Tùy chỉnh các trang lỗi
  • Các trang mã trạng thái tĩnh
  • Xử lý ngoại lệ khởi động

Tạo các HTTP request

Một triển khai của IHttpClientFactory là có sẵn cho việc tạo các lớp khởi tạo HttpClient. Ở factory này:

  • Cung cấp một vị trí trung tập cho việc đặt tên và cấu hình logic các lớp khởi tạo HttpClient. Ví dụ, đăng ký và cấu hình một Github client cho việc truy cập Github. Đăng ký và cấu hình cho một client mặc định cho những mục đích khác.
  • Hỗ trợ đăng ký và liên kết nhiều delegating handler để xây dựng một luồng middleware gửi đi. Pattern này giống với luồng middleware gửi đến của ASP.NET Core. Pattern cung cấp một cơ chế để quản lý các cross-cutting concern của những HTTP request, bao gồm caching, xử lý lỗi, serialization và logging.
  • Tích hợp Polly, một thư viện bên thứ ba nổi tiếng để xử lý lỗi tạm thời.
  • Quản lý pooling và lifetime qua lớp khởi tạo HttpClientHandler để tránh các vấn đề DNS phổ biến xuất hiện khi quản lý lifetime thủ công.
  • Thêm cấu hình logging thông qua ILogger cho tất cả request gửi đến client được tạo bởi factory.

Content root

Content root là base path cho:

  • Tệp thực thi lưu trữ ứng dụng (.exe)
  • Các assembly đã được biên dịch dùng để tạo nên ứng dụng (.dll)
  • Các tệp nội dung được sử dụng trong ứng dụng, chẳng hạn:
    • Các tệp Razor (.cshtml, .razor)
    • Các tệp cấu hình (.json, .xml)
    • Tệp dữ liệu (.db)
  • Web root, thường là thư mục wwwroot.

Trong suốt quá trình phát triển, content root mặc định là đường dẫn thư mục gốc của dự án. Đường dẫn này cũng là base path cho hầu hết các tệp nội dung của ứng dụng và web root. Ta có thể chỉ định một content root khác bằng cách thiết lập đường dẫn của nó khi xây dựng host.

Web root

Web root là base path cho xuất bản, các tệp tài nguyên tĩnh, chẳn hạn:

  • Stylesheets (.css)
  • Javascript (.js)
  • Images (.png, .jpg)

Mặc định, các tệp tĩnh chỉ được cung cấp từ đường dẫn thư mục web root và đường dẫn thư mục con của nó. Đường dẫn web root mặc định là {content root}/wwwroot. Ta có thể chỉ định một web root khác bằng cách thiết lập đường dẫn của nó khi xây dựng host.

Ngăn xuất bản các tệp trong wwwroot với <Content> trong file project. Đoạn code bên dưới ví dụ cho việc ngăn chặn xuất bản nội dung trong thư mục wwwroot/local và các thư mục con của nó:

<ItemGroup>
<Content Update="wwwroot\local\**\*.*" CopyToPublishDirectory="Never" />
</ItemGroup>

Trong các file Razor .cshtml, ~/ trỏ đến web root. Một đường dẫn bắt đầu bằng ~/ được gọi là đường dẫn ảo.

Tổng kết

Qua bài viết này chúng ta đã có cái nhìn tổng quan về các nền tảng mà framework ASP.NET cung cấp. Các bạn đừng quá lo lắng về việc đọc hết cả một bài mà vẫn chưa hiểu rõ vài chỗ, thậm chí là tất cả nội dung trên. Lý do là vì đây chỉ là bức tranh tổng thể để ta nắm bắt được những gì tiếp theo sẽ cùng mình tìm hiểu trong những bài viết tiếp theo. Cảm ơn các bạn đã quan tâm theo dõi, hẹn gặp lại!


  1. Khả năng tương thích ngược (đôi khi được gọi là tương thích ngược) là thuộc tính của hệ điều hành, sản phẩm hoặc công nghệ cho phép khả năng tương tác với hệ thống cũ cũ hơn hoặc với đầu vào được thiết kế cho hệ thống như vậy, đặc biệt là trong viễn thông và máy tính (theo Wikipedia). 

search
Bài viết
Series
Thẻ

Không tìm thấy kết quả nào.