

Tổng quan về Fluent Model và AutoMapper trong ASP.NET Core MVC
- 30-06-2025
- Toanngo92
- 0 Comments
Mục lục
11.1 Giới thiệu về Fluent API và Fluent Model
- Fluent API là một kỹ thuật cấu hình trong Entity Framework giúp định nghĩa các ánh xạ (mapping) và ràng buộc (constraint) giữa các entity và thuộc tính của nó theo cách dễ đọc.
- Dựa vào method chaining (gọi chuỗi phương thức liên tiếp), giúp code rõ ràng và ngắn gọn hơn.
- Fluent API hỗ trợ mapping, cấu hình quan hệ, ràng buộc khóa chính/phụ, kiểu dữ liệu, độ dài chuỗi, v.v.
Fluent Model trong EF
- Entity Framework (EF) ánh xạ các lớp POCO (Plain Old CLR Objects) thành bảng trong CSDL.
- Các class POCO không phụ thuộc EF, và thường dùng với
DbContext
để tạo mô hình dữ liệu. - Khi cần tùy chỉnh vượt quá khả năng của Data Annotation, ta sử dụng Fluent API.
🔹 Ví dụ DbSet
dùng trong DbContext
:
public virtual DbSet<Enrollment> Enrollments { get; set; }
public virtual DbSet<Student> Students { get; set; }
🛠 Một số hàm tiêu biểu trong Fluent API:
ModelBuilder.Entity<TEntityType>()
: Cấu hình entity theo kiểu cụ thể.HasKey<TKey>()
: Định nghĩa khóa chính cho thực thể.
11.2 Lợi ích của Fluent API
Fluent API là cách cấu hình phức tạp hơn, nhưng cung cấp các tính năng mở rộng so với Data Annotation. Một số lợi ích:
- Cung cấp khả năng đọc hiểu tốt (clear visibility)
- Định hướng rõ ràng đến mục tiêu trong code
- Hỗ trợ mapping toàn diện hơn
- Có thể thay thế hoặc bổ sung cho Data Annotation
- Tùy chỉnh chi tiết hơn cấu hình quan hệ, độ dài, ràng buộc
11.3 Làm việc với Fluent API
Quy trình làm việc:
- Tạo ứng dụng ASP.NET Core MVC trong Visual Studio 2022.
- Tạo class model trong thư mục Models.
Ví dụ: tạo classCustomer
trong fileCustomer.cs
, định nghĩa các thuộc tính khách hàng.
(Phần Code Snippet 2
về class Customer
sẽ được trình bày tiếp theo.)
Nếu bạn gửi tiếp trang chứa đoạn mã class Customer
, cấu hình Fluent và tích hợp với AutoMapper, mình sẽ dịch và giải thích phần tiếp theo liền mạch cho bạn.
Dưới đây là bản dịch chi tiết phần tiếp theo của Session 11: Fluent API và AutoMapper trong ASP.NET Core MVC, từ các trang bạn gửi:
Code Snippet 2 – Customer.cs
public class Customer
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
public string Address { get; set; }
}
Bước 3: Tạo lớp Context cho Model
Trong Entity Framework (EF), cần tạo một lớp Context
để thao tác với CSDL.
Dưới đây là nội dung lớp CustomerContext
:
Code Snippet 3 – CustomerContext.cs
public class CustomerContext : DbContext
{
public CustomerContext() : base("name=DBConnectionString") { }
public DbSet<Customer> Customers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>().HasKey(p => p.CustomerId);
modelBuilder.Entity<Customer>().Property(c => c.CustomerName);
base.OnModelCreating(modelBuilder);
}
}
Giải thích:
- Hàm khởi tạo: Gọi base class và chỉ định chuỗi kết nối.
- DbSet<Customer>: Cho phép truy cập tới bảng Customer.
- OnModelCreating(): Dùng Fluent API để cấu hình khóa chính và thuộc tính.
Bảng 11.1: Giải thích mã
Dòng lệnh | Diễn giải |
---|---|
Line 19 | OnModelCreating() nhận đối tượng ModelBuilder – dùng để map các POCO class với CSDL. |
Line 21 | HasKey() định nghĩa khóa chính |
Line 22 | Property() cấu hình thuộc tính |
Code Snippet 4 – Quan hệ với SeniorCitizen.cs
modelBuilder.Entity<SeniorCitizen>().HasRequired(p => p.Customer)
.WithMany(s => s.SeniorCitizen)
.HasForeignKey(s => s.CustomerId);
Thiết lập khóa chính – khóa ngoại giữa
Customer
vàSeniorCitizen
.
Bước 4: Tạo controller – CustomerController.cshtml
Code Snippet 5 – Tạo mới
public ActionResult Create()
{
return View(new Customer());
}
[HttpPost]
public ActionResult Create(Customer Fresh)
{
objContext.Customers.Add(Fresh);
objContext.SaveChanges();
return RedirectToAction("Index");
}
Bước 5: Sửa dữ liệu
Code Snippet 6 – Chỉnh sửa
public ActionResult Edit(int id)
{
Customer customer = objContext.Customers
.Where(x => x.CustomerId == id).SingleOrDefault();
return View(customer);
}
[HttpPost]
public ActionResult Edit(Customer model)
{
Customer customer = objContext.Customers
.Where(x => x.CustomerId == model.CustomerId).SingleOrDefault();
if (customer != null)
{
objContext.Entry(customer).CurrentValues.SetValues(model);
objContext.SaveChanges();
}
return RedirectToAction("Index");
}
Bước 6: Xoá dữ liệu
Code Snippet 7 – Xóa khách hàng
public ActionResult Delete(int id)
{
Customer customer = objContext.Customers.Find(id);
return View(customer);
}
[HttpPost]
public ActionResult Delete(int id, Customer model)
{
var customer = objContext.Customers
.Where(x => x.CustomerId == id).SingleOrDefault();
if (customer != null)
{
objContext.Customers.Remove(customer);
objContext.SaveChanges();
}
return RedirectToAction("Index");
}
Bước 7: Hiển thị danh sách và chi tiết
Code Snippet 8 – Liệt kê và chi tiết
public ActionResult Index()
{
var customers = objContext.Customers.ToList();
return View(customers);
}
public ViewResult Details(int id)
{
Customer customer = objContext.Customers
.Where(x => x.CustomerId == id).SingleOrDefault();
return View(customer);
}
✅ Chạy ứng dụng → CRUD hoạt động với Fluent API trong ASP.NET Core MVC.
11.4 Giới thiệu về AutoMapper
AutoMapper là thư viện nhỏ trong .NET giúp chuyển đổi giữa hai đối tượng với kiểu khác nhau.
→ Còn gọi là Object-to-Object Mapper.
Ví dụ điển hình:
- Chuyển
Customer
→CustomerViewModel
- Tự động ánh xạ các thuộc tính có tên giống nhau
Rất tốt, sau đây là bản dịch chi tiết, đầy đủ, không rút gọn của phần tiếp theo trong Session 11: Fluent API và AutoMapper trong ASP.NET Core MVC, dựa trên các trang bạn vừa cung cấp:
11.5 Các trường hợp sử dụng của AutoMapper
AutoMapper có thể hữu ích trong các tình huống sau:
- Khi các đối tượng có kiểu giống nhau hoặc khác nhau cần được ánh xạ.
- Khi sử dụng các mô hình ứng dụng, còn gọi là các thực thể (Entities), tương ứng với các bảng trong cơ sở dữ liệu.
Ví dụ: đối với một lớp mô hình có tên là Movies
, mỗi trường trong bảng Movies
trong cơ sở dữ liệu sẽ có các thuộc tính tương ứng trong lớp. Trong lớp trình bày (hiển thị dữ liệu), không phải tất cả các trường của Movies
đều cần thiết. Chỉ một vài thuộc tính có thể cần dùng trong giao diện như MovieCode
, MovieName
và MovieBudget
.
Khi gửi dữ liệu từ tầng nghiệp vụ (business layer) đến tầng trình bày (presentation layer), các thuộc tính bổ sung mà không khớp với các mô hình đã được thiết lập trong ứng dụng có thể được yêu cầu. Ví dụ: một vài thuộc tính mới như ReorderLevel
, ReorderValue
, NetPrice
, những trường không tồn tại trong lớp Product
, nhưng lại cần thiết ở tầng trình bày của entity product.
Các lớp mô hình (Model classes) thường khác biệt với các lớp dữ liệu (Data classes) trong các thuộc tính. Để đồng bộ hóa các giá trị, có thể cần ánh xạ một số lượng lớn các lớp hoặc phương thức mà không khớp nhau giữa các lớp nguồn và đích. Khi ứng dụng được xây dựng dựa trên nền tảng Enterprise Application Platform (EAP), nhà phát triển phải ánh xạ thủ công một số lượng lớn mô hình và thuộc tính.
Để ánh xạ giữa các thực thể một cách hiệu quả, AutoMapper được sử dụng. AutoMapper có thể được sử dụng để ánh xạ giữa các đối tượng giống nhau hoặc khác nhau, và nó cũng có thể được sử dụng cho các đối tượng phụ (child objects). Điều này có ích khi sử dụng với các entity tương tác với cơ sở dữ liệu, đồng thời giao tiếp với client.
Ví dụ:
Xem xét hai lớp Movies
và MoviesDTO
như được hiển thị trong Code Snippet 9
, cần được ánh xạ với nhau.
Code Snippet 9
public class Movies
{
public string MovieCode { get; set; }
public string MovieName { get; set; }
public int MovieBudget { get; set; }
}
public class MoviesDTO
{
public string MovieCode { get; set; }
public string MovieName { get; set; }
public int MovieBudget { get; set; }
}
Code Snippet 10
Đoạn mã sau cho thấy cách xây dựng một phương thức ánh xạ nhận đối tượng kiểu MoviesDTO
làm đầu vào và trả về một đối tượng kiểu Movies
.
public Movies MapObjects(MoviesDTO mdto)
{
return new Movies()
{
MovieName = mdto.MovieName,
MovieCode = mdto.MovieCode,
MovieBudget = mdto.MovieBudget
};
}
Mặc dù đoạn mã trên giải quyết được vấn đề, nhưng không thể tái sử dụng dễ dàng khi có nhiều lớp với nhiều thuộc tính tương tự cần được ánh xạ. Trong tất cả các trường hợp đó, AutoMapper sẽ hữu ích.
11.6 Làm việc với AutoMapper
Reflection, được sử dụng trong lập trình C# truyền thống, cung cấp siêu dữ liệu về các assembly, kiểu, phương thức, v.v. Reflection có thể gọi thông tin về lớp thuộc một assembly được chỉ định một cách lập trình.
AutoMapper cũng sử dụng kỹ thuật tương tự. Các bước sau mô tả cách sử dụng AutoMapper với Web API từ ASP.NET Core:
1. Cài đặt AutoMapper
Cài đặt gói:
AutoMapper.Extensions.Microsoft.DependencyInjection
thông qua Package Manager Console, như được minh họa trong Hình 11.2 và Hình 11.3.
🖼 Hình 11.2: Quá trình cài đặt AutoMapper
🖼 Hình 11.3: AutoMapper đã được cài đặt thành công


2. Mở file Program.cs
trong dự án ASP.NET Core
- Thêm
using AutoMapper
ở đầu file. - Thêm dòng cấu hình:
builder.Services.AddAutoMapper(typeof(Program).Assembly);
Dòng này hướng dẫn ASP.NET Core cấu hình AutoMapper và quét tất cả các lớp kế thừa từ lớp Profile
mà nằm trong assembly chứa lớp Program
.
Code Snippet 11
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using AutoMapper;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
// Cấu hình AutoMapper
builder.Services.AddAutoMapper(typeof(Program).Assembly);
// Swagger (tuỳ chọn)
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Cấu hình pipeline xử lý HTTP
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
3. Tạo lớp Movies
Code Snippet 12
public class Movies
{
public string MovieCode { get; set; }
public string MovieName { get; set; }
public int MovieBudget { get; set; }
}
4. Tạo lớp MoviesDTO
Code Snippet 13
public class MoviesDTO
{
public string MovieCode { get; set; }
public string MovieName { get; set; }
public int MovieBudget { get; set; }
}
5. Tạo lớp cấu hình AutoMapperProfile
Code Snippet 14
using AutoMapper;
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<MoviesDTO, Movies>();
}
}
MoviesDTO
hiện đã được ánh xạ tới lớp Movies
. Khi chương trình khởi chạy, AutoMapper sẽ khởi tạo và quét toàn bộ assembly để tìm các lớp kế thừa Profile
, sau đó tải cấu hình ánh xạ tương ứng.
6. Sử dụng AutoMapper trong Controller
Code Snippet 15
using Microsoft.AspNetCore.Mvc;
using AutoMapper;
[ApiController]
[Route("api/[controller]")]
public class MoviesController : ControllerBase
{
private readonly IMapper _mapper;
public MoviesController(IMapper mapper)
{
_mapper = mapper;
}
[HttpGet]
public IActionResult Get()
{
MoviesDTO mDTO = new MoviesDTO()
{
MovieCode = "M001",
MovieName = "ABCD",
MovieBudget = 9000
};
return Ok(_mapper.Map<Movies>(mDTO));
}
}
Trong file Program.cs
, khi dùng cú pháp Minimal API, chúng ta trực tiếp khởi tạo đối tượng MoviesDTO
với các giá trị mẫu. Sau đó, ta lấy service IMapper
từ dịch vụ ứng dụng thông qua app.Services.GetRequiredService<IMapper>()
và dùng phương thức Map
để ánh xạ từ MoviesDTO
sang Movies
.
7. Build và chạy API
Chạy ứng dụng và truy cập endpoint /api/Movies
.
Kết quả sẽ như minh hoạ trong Hình 11.4.
🖼 Hình 11.4: Kết quả của việc sử dụng AutoMapper – hiển thị JSON của đối tượng đã được ánh xạ
11.7 Minimal APIs
Minimal API là một phương pháp xây dựng dịch vụ HTTP đơn giản trong ASP.NET Core. Chúng cung cấp một cách tiếp cận nhẹ nhàng hơn so với controller truyền thống.
Ưu điểm:
- Cú pháp đơn giản, mạch lạc
- Loại bỏ các đoạn mã mẫu (boilerplate)
- Dễ đọc, dễ bảo trì
- Cho phép định nghĩa endpoints và routes rõ ràng, nhanh chóng
Minimal API thích hợp để xây dựng các ứng dụng nhỏ, các microservice hoặc khi cần tạo nhanh RESTful API mà không cần cấu trúc controller đầy đủ.
Lợi ích của Minimal APIs
Dưới đây là một số lợi ích của Minimal APIs:
🟡 Đơn giản hóa (Simplicity)
Minimal APIs đơn giản hóa quá trình tạo dịch vụ HTTP bằng cách loại bỏ yêu cầu phải khai báo các controller và phương thức hành động (action methods).
Nhờ đó, lập trình viên có thể định nghĩa các endpoint và route sử dụng cú pháp ngắn gọn, dẫn đến mã nguồn rõ ràng, dễ đọc và bảo trì hơn.
🟠 Giảm mã mẫu dư thừa (Reduced Boilerplate)
Không giống như các controller trong kiến trúc MVC truyền thống – vốn đòi hỏi phải định nghĩa nhiều lớp controller và phương thức xử lý – Minimal APIs cho phép lập trình viên định nghĩa các route và xử lý request trực tiếp trong một dòng lệnh.
Điều này giúp:
- Loại bỏ mã mẫu không cần thiết
- Tăng năng suất phát triển
- Làm cho ứng dụng nhỏ gọn và linh hoạt hơn
🔴 Phát triển nhanh hơn (Faster Development)
Bằng cách hợp lý hóa (streamlining) quy trình phát triển, Minimal APIs cho phép lập trình viên:
- Xây dựng API nhanh hơn và hiệu quả hơn
- Tập trung vào logic nghiệp vụ thay vì các cấu trúc phức tạp và cấu hình rườm rà
- Mang lại giá trị nhanh chóng cho người dùng cuối
✅ Tóm lại: Minimal APIs là một giải pháp tuyệt vời để xây dựng RESTful API nhỏ gọn, dễ đọc, dễ mở rộng mà không cần nhiều cấu hình hay code thừa như với MVC truyền thống.