Mô hình MVC

Mô hình kiến trúc Model-View-Controller (MVC) phân tách ứng dụng thành 3 nhóm thành phần chính: Models, ViewsControllers. Mô hình này giúp đạt được separation of concerns. Sử dụng mô hình này, các request của người dùng được route đến Controller, Controller làm việc với Model để thực hiện các thao tác và/hoặc truy vấn dữ liệu. Controller chọn View để hiển thị cho người dùng, kèm theo dữ liệu Model cần thiết.

Kiến trúc MVC

Sự phân tách rõ ràng này giúp bạn scale ứng dụng về mặt độ phức tạp vì dễ dàng code, debug và test từng thành phần (model, view, controller). Ngược lại, nếu logic giao diện và business logic combined trong một object, việc thay đổi giao diện sẽ phải sửa object business logic — dễ gây lỗi và đòi hỏi test lại business logic mỗi khi thay đổi giao diện.
Lưu ý: Cả View và Controller đều phụ thuộc vào Model. Tuy nhiên, Model không phụ thuộc vào View hay Controller. Đây là lợi ích chính của sự phân tách này — Model có thể được xây dựng và test độc lập với phần trình bày trực quan.

Trách nhiệm của Model

Model trong ứng dụng MVC đại diện cho trạng thái ứng dụngbusiness logic cần thực hiện. Business logic nên được đóng gói trong model, cùng với logic persistence trạng thái ứng dụng. Strongly-typed views thường sử dụng các loại ViewModel được thiết kế để chứa dữ liệu cần hiển thị trên view đó. Controller tạo và populate các ViewModel instances từ model.

Trách nhiệm của View

Views chịu trách nhiệm trình bày nội dung qua giao diện người dùng. Views sử dụng Razor view engine để nhúng code C# vào HTML markup. Nên có logic tối thiểu trong views, và bất kỳ logic nào trong views cũng chỉ nên liên quan đến trình bày nội dung. Nếu bạn cần thực hiện nhiều logic trong view files để hiển thị dữ liệu từ một model phức tạp, hãy cân nhắc sử dụng View Component, ViewModel, hoặc view template để đơn giản hóa view.

Trách nhiệm của Controller

Controllers là các thành phần xử lý tương tác người dùng, làm việc với Model và cuối cùng chọn View để render. Trong ứng dụng MVC, View chỉ hiển thị thông tin; Controller xử lý và phản hồi input và tương tác của người dùng.
Lưu ý: Controllers không nên quá phức tạp với quá nhiều trách nhiệm. Để tránh logic controller trở nên phức tạp, hãy đẩy business logic ra khỏi controller và đưa vào domain model. Mẹo: Nếu các controller action thường xuyên thực hiện các thao tác giống nhau, hãy chuyển các thao tác chung này thành filters.

ASP.NET Core MVC

Framework ASP.NET Core MVC là một framework trình bày (presentation framework) nhẹ, mã nguồn mở, dễ test cao, được tối ưu cho ASP.NET Core. ASP.NET Core MVC cung cấp cách xây dựng website động dựa trên patterns, cho phép separation of concerns đầy đủ, kiểm soát hoàn toàn markup, hỗ trợ TDD-friendly development và sử dụng các web standards mới nhất.

Routing

ASP.NET Core MVC được xây dựng trên nền ASP.NET Core’s routing — một thành phần ánh xạ URL mạnh mẽ, cho phép xây dựng ứng dụng với URL thân thiện cho SEO và link generation, không phụ thuộc vào cách tổ chức file trên web server. Bạn có thể định nghĩa routes sử dụng route template syntax hỗ trợ route value constraints, defaults và optional values.

Convention-based Routing

Cho phép định nghĩa toàn cục các URL formats mà ứng dụng chấp nhận và cách mỗi format đó map đến một action method cụ thể. Khi request đến, routing engine parse URL và match với một trong các URL formats đã định nghĩa, sau đó gọi action method tương ứng.
app.MapControllerRoute(
    name: "Default",
    pattern: "{controller=Home}/{action=Index}/{id?}"
);
// URL: /Products/Details/5 → ProductsController.Details(5)

Attribute Routing

Cho phép chỉ định routing information bằng cách decorate controllers và actions với attributes định nghĩa routes. Route definitions được đặt ngay cạnh controller và action mà chúng associated.
[Route("api/[controller]")]
public class ProductsController : Controller
{
    [HttpGet("{id}")]
    public IActionResult GetProduct(int id)
    {
        // ...
    }
}

Model Binding

Model binding chuyển đổi dữ liệu request từ phía client (form values, route data, query string parameters, HTTP headers) thành objects mà controller có thể xử lý. Kết quả là logic controller không cần tự xác định dữ liệu incoming request — đơn giản nhận dữ liệu như parameters của action methods.
public async Task<IActionResult> Login(
    LoginViewModel model,      // Từ form/body
    string returnUrl = null   // Từ query string
)
{
    // ...
}

Model Validation

ASP.NET Core MVC hỗ trợ validation bằng cách decorate model object với các data annotation validation attributes. Validation attributes được kiểm tra ở client side trước khi values được post lên server, cũng như ở server side trước khi controller action được gọi.
using System.ComponentModel.DataAnnotations;

public class LoginViewModel
{
    [Required(ErrorMessage = "Email là bắt buộc")]
    [EmailAddress(ErrorMessage = "Email không hợp lệ")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Mật khẩu là bắt buộc")]
    [DataType(DataType.Password)]
    public string Password { get; set; }

    [Display(Name = "Ghi nhớ đăng nhập?")]
    public bool RememberMe { get; set; }
}
public async Task<IActionResult> Login(
    LoginViewModel model,
    string returnUrl = null
)
{
    if (ModelState.IsValid)
    {
        // Xử lý với model
    }
    // Có lỗi, hiển thị lại form
    return View(model);
}
Framework xử lý validating request data cả ở client và server. Validation logic được thêm vào rendered views dưới dạng unobtrusive annotations và được enforce trong browser bằng jQuery Validation.

Dependency Injection

ASP.NET Core có hỗ trợ dependency injection (DI) tích hợp sẵn. Trong ASP.NET Core MVC, các controller có thể yêu cầu services cần thiết thông qua constructors, cho phép tuân theo Explicit Dependencies Principle. Ứng dụng cũng có thể sử dụng dependency injection trong view files bằng directive @inject:
@inject ISomeService ServiceName

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ServiceName.GetTitle()</title>
</head>
<body>
    <h1>@ServiceName.GetTitle()</h1>
</body>
</html>

Filters

Filters giúp developers đóng gói các cross-cutting concerns như exception handling hoặc authorization. Filters cho phép chạy custom pre- và post-processing logic cho action methods, và có thể được configure để chạy ở các điểm nhất định trong execution pipeline cho một request. Filters có thể được apply vào controllers hoặc actions như attributes (hoặc chạy globally). Một số filters (như Authorize) đã có sẵn trong framework.
[Authorize]
public class AccountController : Controller
{
    [HttpGet]
    [AllowAnonymous]
    public IActionResult Login() => View();
}

Areas

Areas cung cấp cách phân chia ứng dụng ASP.NET Core MVC thành các nhóm chức năng nhỏ hơn. Một Area là một cấu trúc MVC bên trong ứng dụng. Trong một MVC project, các thành phần logic như Model, Controller và View được giữ trong các folders khác nhau, và MVC sử dụng naming conventions để tạo mối quan hệ giữa các thành phần này. Với các ứng dụng lớn, việc phân chia thành các areas riêng biệt theo chức năng là rất có lợi — ví dụ một ứng dụng thương mại điện tử với nhiều đơn vị kinh doanh như checkout, billing, search. Mỗi đơn vị có các components riêng về views, controllers và models.

Web APIs

Ngoài việc là nền tảng tuyệt vời để xây dựng websites, ASP.NET Core MVC còn có hỗ trợ rất tốt cho việc xây dựng Web APIs phục vụ nhiều loại clients khác nhau bao gồm browsers và mobile devices. Framework bao gồm hỗ trợ HTTP content-negotiation với khả năng format data thành JSON hoặc XML. Bạn có thể viết custom formatters để thêm hỗ trợ format riêng. Sử dụng link generation để hỗ trợ hypermedia. Dễ dàng enable hỗ trợ Cross-Origin Resource Sharing (CORS) để Web APIs có thể được chia sẻ giữa nhiều ứng dụng web.

Testability

Việc sử dụng interfacesdependency injection khiến framework rất phù hợp cho unit testing, và framework còn cung cấp các tính năng (như TestHostInMemory provider cho Entity Framework) giúp integration tests nhanh và dễ dàng.

Razor View Engine

ASP.NET Core MVC views sử dụng Razor view engine để render views. Razor là ngôn ngữ template nhỏ gọn, giàu tính diễn đạt và linh hoạt để định nghĩa views sử dụng embedded C# code. Razor được dùng để tạo web content động trên server. Bạn có thể thoải mái mix server code với client side content.
<ul>
@for (int i = 0; i < 5; i++)
{
    <li>List item @i</li>
}
</ul>
Sử dụng Razor view engine, bạn có thể định nghĩa layouts, partial viewsreplaceable sections.

Strongly Typed Views

Razor views trong MVC có thể được strongly typed dựa trên model. Controllers truyền strongly typed model cho views, cho phép views có type checking và hỗ trợ IntelliSense.
@model IEnumerable<Product>

<ul>
@foreach (Product p in Model)
{
    <li>@p.Name</li>
}
</ul>

Tag Helpers

Tag Helpers cho phép server-side code tham gia tạo và render các HTML elements trong Razor files. Bạn có thể sử dụng Tag Helpers để định nghĩa custom tags (ví dụ <environment>) hoặc modify behavior của các tags hiện có (ví dụ <label>). Tag Helpers bind vào các elements dựa trên element name và attributes của nó. Có nhiều built-in Tag Helpers cho các tác vụ phổ biến — như tạo forms, links, loading assets — và nhiều hơn nữa có sẵn trong public GitHub repositories và NuGet packages. Tag Helpers được viết bằng C#, target HTML elements dựa trên element name, attribute name hoặc parent tag.
<p>
    Cảm ơn bạn đã xác nhận email.
    Vui lòng <a asp-controller="Account" asp-action="Login">đăng nhập tại đây</a>.
</p>

Tải Script theo môi trường

<environment names="Development">
    <script src="~/lib/jquery/dist/jquery.js"></script>
</environment>

<environment names="Staging,Production">
    <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.js"
            asp-fallback-src="~/lib/jquery/dist/jquery.js"
            asp-fallback-test="window.jQuery">
    </script>
</environment>
Tag Helpers cung cấp trải nghiệm HTML-friendly và môi trường IntelliSense phong phú. Hầu hết built-in Tag Helpers target các HTML elements hiện có và cung cấp server-side attributes cho element đó.

View Components

View Components cho phép đóng gói logic rendering và tái sử dụng throughout the application. Chúng giống như partial views, nhưng có logic đi kèm.

Compatibility Version

Phương thức SetCompatibilityVersion cho phép ứng dụng opt-in hoặc opt-out các thay đổi potentially breaking behavior được giới thiệu trong ASP.NET Core MVC 2.1 trở lên.
builder.Services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_10_0);

Tài liệu tham khảo