Routing trong ASP.NET Core MVC

0

Routing trong ASP.NET Core là quá trình ánh xạ (mapping) truy vấn HTTP với một đối tượng xử lý truy vấn đó (handler). Trong MVC, handler chính là phương thức action của controller.

Như vậy, routing trong ASP.NET Core MVC là cơ chế ánh xạ giữa truy vấn HTTP và controller action.

Hiểu một cách đơn giản, khi truy vấn tới, cơ chế routing xác định xem có action nào tương ứng với nó hay không để thực thi. Khi xây dựng một controller và các action, routing xác định một tập hợp các Url hợp lệ tương ứng cho controller và action đó.

Routing thực ra không phải là một phần của kiến trúc MVC. Routing là cơ chế thường gặp trong các web framework. Bạn cũng đã từng học về routing trong Razor Pages.

Routing mặc định của dự án MVC

Trước mắt hãy cùng xem xét loại routing mặc định mà ASP.NET Core MVC sử dụng cho một project mới.

Khi cấu hình sử dụng Mvc Middleware, bạn bắt buộc phải chỉ định ít nhất một route template trong phương thức Configure của Startup.cs sử dụng phương thức UseEndpoints như sau:

app.UseEndpoints(endpoints => {
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

Trong phương thức này bạn có thể định nghĩa thêm các template của mình. Chúng ta sẽ nói về vấn đề này ở phần sau của bài học.

"{controller=Home}/{action=Index}/{id?}" là route template mặc định ASP.NET Core sử dụng cho các dự án MVC. Đây là cơ chế conventional routing, áp dụng chung cho toàn bộ controlleraction của ứng dụng.

Template này quy định rằng phần path của một Url hợp lệ phải có dạng {controller}/{action}hoặc {controller}/{action}/{id}. Trong đó:

  • {controller}, {action} và {id} được gọi là các placeholder hay route parameter.
  • Ký tự / phân chia chuỗi template thành các segment.
  • Home và Index được gọi là giá trị mặc định tương ứng của controller và action.
  • {id?} là không bắt buộc.

Đây là một template rất tổng quát.

Khi sử dụng template này, ASP.NET Core sẽ tách URL của truy vấn thành các segment. Hai segment đầu tiên cho phép rút ra thông tin về controller và action. Dựa trên thông tin này ASP.NET Core sẽ tìm kiếm controller và action phù hợp để thực thi.

Nếu có segment thứ 3, giá trị của segment này sẽ đưa vào một biến có tên id để truyền cho action. Segment thứ 3 không bắt buộc.

Khi bạn tạo một controller mới với các action trong đó, các action này tự động có URL phù hợp. Bạn không cần tự mình cấu hình router riêng. Khi nhìn thấy một Url, bạn có thể dự đoán được ngay action trong controller nào sẽ được gọi khi phát đi truy vấn.

Routing trong ASP.NET Core MVC

ASP.NET Core MVC cung cấp hai cơ chế routing: conventional routingattibute routing.

Conventional routing là loại routing được định nghĩa chung cho toàn ứng dụng dựa trên một số quy ước xác định. Bất kỳ controller và action nào tuân theo quy ước đều tự động tham gia vào routing tương ứng.

Conventional routing đơn giản, tiện lợi, dễ theo dõi và quản lý. Controller và action phải tuân theo quy ước thì mới áp dụng được routing.

Đây là loại routing được sử dụng mặc định cho ứng dụng ASP.NET Core MVC.

Attribute routing là loại routing được định nghĩa riêng rẽ cho từng action bằng cách đặt attribute [Route] trước mỗi action.

Attribute routing có ý tưởng ngược lại so với conventional routing. Trong attribute routing bạn xuất phát từ action và định nghĩa Url tương ứng cho nó. Ở chiều ngược lại, conventional routing đưa ra khuôn mẫu Url và bạn xây dựng controller/action tuân thủ khuôn mẫu.

Loại routing này linh hoạt hơn nhiều so với conventional routing song lại khó theo dõi và quản lý hơn. Khi sử dụng attribute routing, bạn cần tự mình quản lý một danh sách các routing riêng rẽ.

Phương pháp routing này hữu dụng hơn khi xây dựng Web API.

Mvc Middleware cho phép cung cấp và sử dụng đồng thời cả hai phương pháp routing và nhiều cấu trúc ánh xạ khác nhau.

Mỗi cấu trúc ánh xạ được gọi là một router hoặc route template.

Route template là những chuỗi ký tự định nghĩa cấu trúc cho các URL hợp lệ của ứng dụng.

Dù sử dụng phương pháp nào, cuối cùng bạn cũng đều phải định nghĩa route template.

Chúng ta sẽ nói chi tiết về cấu trúc của route template ở phần sau của bài học.

Conventional routing trong ASP.NET Core MVC

Conventional routing được định nghĩa trong phương thức Configure của Startup.cs:

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

    app.UseRouting();

    app.UseEndpoints(endpoints => {
        endpoints.MapControllerRoute("default", "{controller = Home}/{action = Index}/{id?}");
    });
}

Mỗi template được định nghĩa bởi một lần gọi phương thức MapControllerRoute. Phương thức này tối thiểu chứa tên template và chuỗi template. Tên template được dùng trong lệnh sinh URL.

Mặc định ASP.NET Core MVC định nghĩa sẵn cho bạn “default” template.

Bạn có thể định nghĩa bao nhiêu template tùy thích. Nếu có nhiều route template, ASP.NET Core MVC sẽ so khớp lần lượt với từng template theo thứ tự khai báo cho đến khi tìm được route phù hợp. Bạn nên bố trí template cụ thể hơn ở trên, template tổng quát hơn ở dưới.

Giờ hãy điều chỉnh phương thức UseEnpoints như sau:

app.UseEndpoints(endpoints => {
    endpoints.MapControllerRoute("my-route-1", "hi/{fname}-{lname}", new { controller = "Default", action = "Hi" });
    endpoints.MapControllerRoute("my-route-2", "web/{action}/{controller}");
    endpoints.MapControllerRoute("default", "{controller = Home}/{action = Index}/{id?}");
});

Bạn đã xây dựng hai route template mới. “my-route-1” ánh xạ những Url như hi/Donald-Trump, hi/Vladimir-Putin vào phương thức action Hi của DefaultController. “my-route-2” cho phép gọi đến DefaultController.Hi() qua Url web/hi/default.

Trong hai template mới, my-route-2 tổng quát hơn vì nó áp dụng được với nhiều controller và action. my-route-1 cụ thể hơn vì nó chỉ áp dụng duy nhất cho DefaultController.Hi().

Bạn có thể từ tạo controller đặt tên là HomeController và tạo action Index trong đó để thử nghiệm.

using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers {
    public class DefaultController : Controller {       
        public IActionResult Hi(string fname, string lname) {
            return View((fname, lname));
        }
    }
}

Trong template my-route-1 có 2 segment: hi và {fname}-{lname}. Segment thứ nhất (hi) được gọi là literal segment. Segment thứ hai là tổ hợp của hai route parameter {fname}{lname} phân tách bởi ký tự -.

Do từ chuỗi template không xác định được sẽ gọi controller và action nào, bạn cung cấp thêm một object thuộc kiểu vô danh, trong đó chỉ rõ controller sẽ luôn nhận giá trị Default, và action luôn nhận giá trị Hi. Object này đảm bảo rằng nếu Url tới phù hợp, action Hi của DefaultController sẽ luôn được gọi.

Cơ chế routing của ASP.NET Core so khớp Url tới xem nó trùng khớp với khuôn mẫu nào. Nếu trùng với mẫu my-route-1, chuỗi ký tự ở vị trí tương ứng fname và lname sẽ được tách ra và đặt vào trong một object dạng từ điển để truyền vào action.

Để hiểu rõ hơn cách tạo route, chúng ta phải biết về cấu trúc của một route template.

Cấu trúc route template trong conventional routing

Segment và parameter

Route template được phân chia thành segment. Mỗi segment có thể là:

  • Một chuỗi ký tự “tĩnh” gọi là literal segment. Như trong my-route-1, hi chính là một literal segment. Literal segment yêu cầu phải hoàn toàn trùng khớp nhưng không phân biệt hoa thường. Trong template “hi/{fname}-{lname}”, segment đầu tiên bắt buộc phải là hi, Hi, HI, hay hI.
  • Thành phần “động” gọi là placeholder hoặc parameter. Placeholder trong template được thể hiện trong cặp dấu {}. Đây là thành phần phức tạp và tạo ra sự linh hoạt của route template. Có hai loại placeholder: (1) loại do ASP.NET Core MVC định nghĩa sẵn và bắt buộc, bao gồm {controller}{action}; (2) loại do bạn tự đặt ra (như {lname} và {fname} bên trên).
  • Tổ hợp của cả literal và route parameter. Đây chính là cách chúng ta tạo ra segment thứ hai của template “hi/{fname}-{lname}”.

Bạn bắt buộc phải có cách chỉ định {controller} và {action} khi thêm route template. Chỉ định này giúp cơ chế routing của ASP.NET Core MVC xác định controller và action xử lý truy vấn.

Nếu hai placeholder này không nằm sẵn trong chuỗi template, bạn phải cung cấp một object vô danh để chỉ định rõ giá trị của controller và action. Đây cũng là cách chúng ta sử dụng khi khai báo my-route-1.

Đối với parameter do bạn tự định nghĩa, bạn sử dụng nó như là cơ chế truyền dữ liệu từ Url vào action. Cơ chế routing có khả năng trích phần giá trị tương ứng của parameter và truyền vào làm tham số của action. Đây lại là một phần của cơ chế model binding mà chúng ta sẽ học ở một bài khác.

Như trong ví dụ trên, fname và lname cũng đồng thời là hai tham số của action Hi(string fname, string lname).

Số lượng segment và placeholder trong mỗi route hoặc template không hạn chế, có thể bắt buộc hoặc tùy chọn, có thể chịu các giới hạn nhất định.

Paramter tùy chọn và parameter bắt buộc

Trong route template, mặc định mỗi parameter đều là bắt buộc. Nghĩa là nếu bạn đã đặt một parameter vào template, trong Url bắt buộc phải có phần tương ứng với parameter. Nếu thiếu, Url không phù hợp với template.

Nếu bạn muốn một parameter trở thành không bắt buộc, nghĩa là ở vị trí đó có thể có hoặc có thể không đặt giá trị gì, bạn đặt thêm ký tự ? ở sau tên parameter.

Ví dụ, trong route template mặc định “{controller=Home}/{action=Index}/{id?}”, {id?} là một parameter tùy chọn, trong khi {controller} và {action} là bắt buộc.

Khi này, cả hai Url Home/Index và Home/Index/3 đều phù hợp (với giả định rằng có HomeController và Index action).

Giá trị mặc định của parameter

Paramter có thể nhận giá trị mặc định bằng cách thêm =giá-trị vào sau tên paramter. Trong route mặc định “{controller=Home}/{action=Index}/{id?}”, controller có giá trị mặc định là Home, và action có giá trị mặc định là Index.

Sử dụng giá trị mặc định cho phép bỏ qua paramter tương ứng.

Ví dụ: Url /, /home và /home/index đều ánh xạ sang Index action của HomeController.

Theo đó, / tương ứng với bỏ qua cả controller, action và id; /home tương ứng với bỏ qua action và id

Một số giới hạn khác:

ASP.NET Core MVC cho phép cung cấp thêm những giới hạn đối với parameter trong route template. Đây là những giới hạn về kiểu và phạm vi giá trị.

Bạn đặt thêm giới hạn vào sau tên parameter và phân tách bằng dấu hai chấm.

Bạn cũng có thể kết hợp nhiều giới hạn với nhau. Khi có nhiều giới hạn, bạn cũng phân tách chúng bằng dấu hai chấm.

Bảng sau đây giới thiệu một số loại giới hạn thường dùng:

Một số vấn đề về URL

Qua nội dung của bài học bạn có thể thấy ASP.NET Core MVC rất linh hoạt trong định nghĩa khuôn mẫu URL. Cơ chế routing cho phép bạn định nghĩa ra gần như bất kỳ khuôn mẫu URL nào bạn muốn.

Khi xây dựng ứng dụng web nói chung, bạn nên lưu ý về việc lựa chọn cấu trúc URL. Đặc biệt nếu ứng dụng triển khai trên Internet và tham gia vào máy tìm kiếm.

Thứ nhất, hãy cố gắng tạo cấu trúc URL ngắn gọn và đơn giản.

Bạn hẳn sẽ dễ nhớ những URL như https://tuhocict.com/about, https://tuhocict.com/blog.

Cấu trúc này không khớp với template mặc định của dự án MVC.

Với những trường hợp như thế này bạn có thể sử dụng attribute routing [Route("about")] hoặc [Route("blog")] trước action tương ứng.

Nếu sử dụng conventional routing, bạn có thể sử dụng khai báo template sau:

endpoints.MapControllerRoute("about", "about", new { controller = "Home", action = "About" });

Thứ hai, bạn nên sử dụng những cấu trúc Url thân thiện với máy tìm kiếm (nếu có thể). Điều này đặc biệt cần thiết nếu ứng dụng của bạn thiên về quản lý nội dung trên Internet như blog hoặc trang tin tức.

Ví dụ, Url thân thiện với máy tìm kiếm như https://tuhocict.com/blog/routing-trong-asp-net-core-mvc.

Giả sử nội dung mỗi bài viết được tạo ra từ BlogController.Article action, bạn có thể sử dụng template:

endpoints.MapControllerRoute("article", "blog/{slug}", new { controller = "Blog", action = "Article" });

Trong đó slug (mượn tạm thuật ngữ của wordpress) là một chuỗi ký tự tạo ra từ tên bài viết và loại bỏ đi các ký tự đặc biệt. Các từ trong tên gọi ghép với nhau bởi dấu gạch ngang. Slug dùng làm tham số cho Article. Template này cũng chỉ định luôn action tiếp nhận Url.

Tuy nhiên đối với site quản lý (hoặc phần backend), bạn không cần tạo các url đẹp như vậy do bạn cần cung cấp nhiều tham số cho action qua Url.

Thứ ba, nếu cần cung cấp tham số cho action thông qua Url, bạn có thể sử dụng query string (?fname=Donald&lname=Trump) hoặc route parameter ({fname} và {lname} trong route template).

Action xử lý Url phải có các tham số đầu vào tương ứng trùng tên.

Cơ chế routing kết hợp với model binding sẽ tự động trích giá trị và truyền vào tham số tương ứng của action.

Khi truyền tham số qua Url, bạn nên kết hợp các giới hạn về kiểu hoặc khoảng giá trị trong route template.

Kết luận

Bài học đã giới thiệu chi tiết về cơ chế routing trong ASP.NET Core MVC. Khi hiểu cơ chế này bạn có thể dễ dàng xây dựng thêm các route template để ánh xạ với action mình xây dựng. ASP.NET Core MVC cho phép bạn xây dựng ra gần như bất kỳ cấu trúc URL nào.

Nếu có thắc mắc hoặc cần trao đổi thêm, mời bạn viết trong phần Thảo luận cuối trang.
Nếu cần trao đổi riêng với chúng tôi, hãy gửi email hoặc nhắn tin qua form liên hệ.
Nếu bài viết hữu ích với bạn, hãy giúp chúng tôi chia sẻ tới mọi người.
Đăng ký theo dõi trang facebook để nhận thông tin về bài viết mới.
Tắt Adblocker hoặc whitelist trang để hỗ trợ chúng tôi.
Cảm ơn bạn!

* Bản quyền bài viết thuộc về Tự học ICT. Đề nghị tôn trọng bản quyền. DMCA.com Protection Status
Subscribe
Notify of
guest
0 Thảo luận
Inline Feedbacks
View all comments