Phần 2: Thêm Controller vào ứng dụng ASP.NET Core MVC
Pattern kiến trúc Model-View-Controller (MVC) tách một ứng dụng thành ba thành phần chính: Model (mô hình), View (giao diện) và Controller (bộ điều khiển). Pattern MVC giúp bạn tạo các ứng dụng dễ kiểm thử hơn và dễ cập nhật hơn so với các ứng dụng monolithic (đơn khối) truyền thống.
Các ứng dụng dựa trên MVC chứa:
- Model: Các class đại diện cho dữ liệu của ứng dụng. Các class model sử dụng validation logic (logic xác thực) để thực thi các business rules (quy tắc nghiệp vụ) cho dữ liệu đó. Thông thường, các object model truy xuất và lưu trữ trạng thái model trong database. Trong hướng dẫn này, một
Moviemodel truy xuất dữ liệu phim từ database, cung cấp cho view hoặc cập nhật nó. Dữ liệu đã cập nhật được ghi vào database. - View: Các view là các thành phần hiển thị giao diện người dùng (UI) của ứng dụng. Nói chung, UI này hiển thị dữ liệu model.
- Controller: Các class:
- Xử lý các yêu cầu trình duyệt.
- Truy xuất dữ liệu model.
- Gọi các view template (mẫu giao diện) trả về một response (phản hồi).
Trong ứng dụng MVC, view chỉ hiển thị thông tin. Controller xử lý và phản hồi các input và tương tác của người dùng. Ví dụ, controller xử lý các URL segment (đoạn URL) và giá trị query-string, rồi truyền các giá trị này vào model. Model có thể sử dụng các giá trị này để query database. Ví dụ:
https://localhost:5001/Home/Privacy: chỉ định controllerHomevà actionPrivacy.https://localhost:5001/Movies/Edit/5: là một yêu cầu chỉnh sửa bộ phim có ID=5 bằng cách sử dụng controllerMoviesvà actionEdit, được trình bày chi tiết sau trong hướng dẫn.
Route data (dữ liệu định tuyến) được giải thích sau trong hướng dẫn.
Pattern kiến trúc MVC tách một ứng dụng thành ba nhóm thành phần chính: Models, Views và Controllers. Pattern này giúp đạt được separation of concerns (phân tách mối quan tâm): Logic UI thuộc về view. Logic input thuộc về controller. Business logic thuộc về model. Sự phân tách này giúp quản lý sự phức tạp khi xây dựng ứng dụng, vì nó cho phép làm việc trên một khía cạnh của việc triển khai tại một thời điểm mà không ảnh hưởng đến code của phần khác.
Các khái niệm này được giới thiệu và trình bày trong loạt bài hướng dẫn này trong khi xây dựng ứng dụng phim. Dự án MVC chứa các thư mục cho Controllers và Views.
Thêm controller
Visual Studio
Trong Solution Explorer, nhấp chuột phải vào Controllers > Add > Controller.
Trong hộp thoại Add New Scaffolded Item, chọn MVC Controller - Empty > Add.
Trong hộp thoại Add New Item - MvcMovie, nhập HelloWorldController.cs và chọn Add.
Visual Studio Code
Chọn biểu tượng EXPLORER rồi nhấp chuột phải vào Controllers > New File và đặt tên tệp mới là HelloWorldController.cs.
Thay thế nội dung của Controllers/HelloWorldController.cs bằng code sau:
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;
namespace MvcMovie.Controllers;
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/
public string Index()
{
return "This is my default action...";
}
//
// GET: /HelloWorld/Welcome/
public string Welcome()
{
return "This is the Welcome action method...";
}
}Mọi phương thức public trong một controller đều có thể được gọi như một HTTP endpoint. Trong mẫu trên, cả hai phương thức đều trả về một chuỗi.
Một HTTP endpoint:
- Là một URL có thể truy cập trong ứng dụng web, chẳng hạn như
https://localhost:5001/HelloWorld. - Kết hợp:
- Protocol (giao thức) được sử dụng:
HTTPS. - Network location (vị trí mạng) của web server, bao gồm TCP port:
localhost:5001. - Target URI:
HelloWorld.
Comment đầu tiên nói rằng đây là phương thức HTTP GET được gọi bằng cách thêm /HelloWorld/ vào base URL.
Comment thứ hai chỉ định một phương thức HTTP GET được gọi bằng cách thêm /HelloWorld/Welcome/ vào URL. Ở phần sau trong hướng dẫn, scaffolding engine (công cụ scaffolding) được sử dụng để tạo các phương thức HTTP POST, cập nhật dữ liệu.
Chạy ứng dụng không có debugger bằng cách nhấn Ctrl+F5.
Thêm /HelloWorld vào path trong thanh địa chỉ. Phương thức Index trả về một chuỗi.
MVC gọi các class controller và các action method (phương thức hành động) trong chúng, tùy thuộc vào URL đến. URL routing logic mặc định được MVC sử dụng, sử dụng định dạng như sau để xác định code nào sẽ được gọi:
/[Controller]/[ActionName]/[Parameters]
Định dạng routing được đặt trong tệp Program.cs.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");Khi bạn duyệt đến ứng dụng và không cung cấp bất kỳ URL segment nào, nó mặc định sử dụng controller "Home" và phương thức "Index" được chỉ định trong dòng template được tô sáng ở trên. Trong các URL segment trước:
- URL segment đầu tiên xác định class controller cần chạy. Vì vậy
localhost:5001/HelloWorldánh xạ đến class HelloWorld Controller. - Phần thứ hai của URL segment xác định action method trên class. Vì vậy
localhost:5001/HelloWorld/Indexlàm cho phương thứcIndexcủa classHelloWorldControllerchạy. Lưu ý rằng bạn chỉ cần duyệt đếnlocalhost:5001/HelloWorldvà phương thứcIndexđược gọi theo mặc định.Indexlà phương thức mặc định sẽ được gọi trên một controller nếu tên phương thức không được chỉ định rõ ràng. - Phần thứ ba của URL segment (
id) là cho route data. Route data được giải thích sau trong hướng dẫn.
Duyệt đến: https://localhost:{PORT}/HelloWorld/Welcome. Thay thế {PORT} bằng số port của bạn.
Phương thức Welcome chạy và trả về chuỗi This is the Welcome action method.... Đối với URL này, controller là HelloWorld và Welcome là action method. Bạn chưa sử dụng phần [Parameters] của URL.
Truyền tham số từ URL
Sửa đổi code để truyền một số thông tin tham số từ URL vào controller. Ví dụ, /HelloWorld/Welcome?name=Rick&numtimes=4.
Thay đổi phương thức Welcome để bao gồm hai tham số như trong code sau.
// GET: /HelloWorld/Welcome/
// Requires using System.Text.Encodings.Web;
public string Welcome(string name, int numTimes = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, NumTimes is: {numTimes}");
}Code trước:
- Sử dụng tính năng optional-parameter (tham số tùy chọn) của C# để chỉ ra rằng tham số
numTimesmặc định là 1 nếu không có giá trị nào được truyền cho tham số đó. - Sử dụng
HtmlEncoder.Default.Encodeđể bảo vệ ứng dụng khỏi input độc hại, chẳng hạn như thông qua JavaScript. - Sử dụng Interpolated Strings trong
$"Hello {name}, NumTimes is: {numTimes}".
Chạy ứng dụng và duyệt đến: https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4.
Thử các giá trị khác nhau cho name và numtimes trong URL. Hệ thống model binding (ràng buộc model) MVC tự động ánh xạ các tham số được đặt tên từ query string (chuỗi truy vấn) sang các tham số trong phương thức.
Trong hình ảnh trước:
- URL segment
Parameterskhông được sử dụng. - Các tham số
namevànumTimesđược truyền trong query string. ?(dấu hỏi) trong URL ở trên là dấu phân cách và query string theo sau.- Ký tự
&phân tách các cặp field-value.
Sử dụng Route Parameter
Thay thế phương thức Welcome bằng code sau:
public string Welcome(string name, int ID = 1)
{
return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}");
}Chạy ứng dụng và nhập URL sau: https://localhost:{PORT}/HelloWorld/Welcome/3?name=Rick
Trong URL trước:
- URL segment thứ ba khớp với route parameter
id. - Phương thức
Welcomechứa tham sốidkhớp với URL template trong phương thứcMapControllerRoute. ?ở cuối bắt đầu query string.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");Trong ví dụ trước:
- URL segment thứ ba khớp với route parameter
id. - Phương thức
Welcomechứa tham sốidkhớp với URL template trong phương thứcMapControllerRoute. ?ở cuối (trongid?) chỉ ra rằng tham sốidlà tùy chọn.