(ASP.NET Core MVC) Tạo ứng Dụng MVC đầu Tiên C# CSharp
Có thể bạn quan tâm
- Lập trình PHP
- PSR
- Laminas
- SPL
- Xenforo
- Zend Framework
- Lập trình ứng dụng iOS - Swift
- Ruby
- Sketchup
- Lập trình Dart - Flutter
- Lập trình C# (C Sharp)
- Lập trình C# Cơ bản
- Server
- MySql Server
- Windows
- Apache
- PHP
- HTML
- Javascript
- JQuery
- TypeScript - Angular
- CSS
- Sử dụng SASS / SCSS
- Bootstrap - CSS Framework
- SQL
- SQL Server ( .NET Framework - C#)
- MS Access
- Java
- Android Java
- Thuật ngữ - Các vấn đề cơ bản
- Tools
- Git và GitHub
- Kubernetes
- Mathematica
- SSH - Secure Shell
- Grunt
- Elasticsearch
- Docker
- macOS
- English Study
- Tin tức công nghệ
- Tri thức & Khoa học
- Yoga
- Lập trình C# (C Sharp)
- Lập trình C# Cơ bản
Lập trình ASP.NET Core MVC, bài học về mô hình lập trình MVC, khởi tạo ứng dụng ASP.NET MVC , cách hoạt động của ASP.NET MVC, sử dụng Route ánh xạ Request, tạo và sử dụng các Controller các View .cshtml, truyền dữ liệu Controller - View với ViewBag, Model
Bắt đầu từ bài này chúng ta sẽ tìm hiểu về lập trình ASP.NET MVC, lập trình ứng dụng web với mô hình hiện đại, hoạt động của dự án được chia ra thành các tầng - lớp để dễ dàng bảo trì - mở rộng. Bài học đầu tiên về ASP.NET MVC gồm các mục:
- Tạo ứng dụng ASP.NET MVC
- SSL - kích hoạt https ASP.NET Core
- Route ASP.NET MVC
- Tạo Controller ASP.NET MVC
- Tạo View ASP.NET MVC
- Truyền dữ liệu Controller tới View với ViewBag
- Truyền dữ liệu Controller tới View với Model
- Phát sinh mã, cấu trúc với aspnet-codegenerator
Tạo ứng dụng ASP.NET MVC đầu tiên
MVC đó là một mô hình lập trình, có gắng chia code thành 3 phần: model triển khai các mô hình dữ liệu, truy cập dữ liệu. view biểu diễn dữ liệu cho người dùng, controller nhận các yêu cầu browser gửi đến và trả về http response.Trong NET Core 3.x tạo ứng dụng mẫu ASP.NET MVC nhanh từ template bằng lệnh
dotnet new mvcHãy tạo ra một thư mục mẫu đặt tên là mvc01_HelloWorld, vào thư mục đó, rồi gõ lệnh trên để tạo dự án thực hành.
Dự án mẫu tạo ra là cấu trúc cơ bản cho ứng dụng ASP.NET CORE MVC. Trong tổ chức thư mục dự án thấy có:
- Controllers : nơi chứa các lớp sẽ nhận yêu cầu gửi đến và trả về nội dung HTTP Response.
- Models: nơi chứa các lớp cung cấp, xử lý dữ liệu
- Views: chứa các file .cshtml để dựng HTML
- wwwroot: chứa các file tĩnh (hình ảnh, js, css ...). Trong thư mục này đã copy sẵn thư viện CSS Bootstrap và JS JQuery
Kết quả chạy trang web như hình sau:
Một số khái quát chung
- Controller: Một lớp C# do bạn định nghĩa kế thừa từ lớp Microsoft.AspNetCore.Mvc.Controller, khi các truy vấn đến ứng dụng tùy thuộc vào cấu hình, căn cứ vào URL truy cập mà controller được khởi tạo và thiết lập vào nó (trong các property) tất cả thông tin của một reques, và một phương thức trong controller (một action) được thực thi để xử lý truy vấn.
- Action: Các action là những phương thức public (không là static, không overloaded) trong controller được gọi tự động tùy thuộc vào sự điều hướng của route trong ứng dụng (căn cứ vào URL). Action trả về các kiểu triển khai từ IActionResult như ViewResult, EmptyResult, FileContentResult, RedirectResult, JsonResult ... đó là respone sẽ trả về cho browser.
Tương ứng trong controller có sẵn các phương thức để trả về kiểu tương ứng trên như: View, Redirect, RedirectToAction, Content, File ..., một số Action có thể trả về không phải kiểu triển khai từ IActionResult thì nó tự động tạo ContentResult
Các request (truy vấn) được ánh xạ vào action thông qua routing. Các Action thường trả về bằng cách gọi phương thức View(), View(model). - View: Là các file .cshtml tích hợp sẵn cú pháp Razor (razor engine), (hãy xem về Razor Page để biết cú pháp viết trong view .cshtml) được tổ chức thành các thư mục cho từng Controller. Nếu controller tên là Home thì các view đặt trong thự mục /View/Home, tên các file view tương ứng tên Action của Controller, qua đó nó được dùng để dựng HTML.
Truy cập ứng dụng với HTTPS
Mở file Startup.cs ra, thấy mã sinh ra có đưa vào pipeline một Middleware là HttpsRedirection với lệnh app.UseHttpsRedirection();. Điều này có nghĩa ứng dụng tạo ra mặc định chỉ truy cập bởi https, sau này trên môi trường sản phẩm bạn cần cấu hình Web Server như Apache, Nginx, IIS để xác thực ssl. Tuy nhiên, ở môi trường phát triển bạn cần tự xác thực SSL - nếu không thì có lỗi truy cập. Công cụ dotnet hỗ trợ làm điều này, bạn thực hiện lệnh sau:
dotnet dev-certs https --clean dotnet dev-certs https --trustSau đó bạn đã có thể truy cập được đến https://localhost:5001
Route - Định tuyển trong ASP.NET MVC
Routing (định tuyển) là quá quá trình xử lý thông qua nó ứng dụng xác định được cần thi hành các phương thức nào cho mỗi URL gửi đến. ASP.NET Core sử dụng một middleware để ánh xạ các URL tương ứng với phương thức nào của ứng dụng. Cụ thể hơn, Route xác định được phương thức (action) trong Controller - qua đó nó chuyển các thông tin Request đến và thi hành.Để định tuyển, đã trình bày trong phần trước ví dụ như Sử dụng EndpointMiddleware để tạo các điểm cuối rẽ nhánh trong pipeline trong UseEndpoints với các phương thức như Map, MapGet, MapPost ...
Đồng thời cũng đã nói về rẽ nhánh bằng cách sử dụng IApplicationBuilder.Map
Trong phần này, khi mở rộng dự án áp dụng MVC sử dụng thêm các phương thức tạo điểm cuối rẽ nhánh khi sử dụng với EndpointMiddleware, đầu tiên là MapControllerRoute
IEndpointRouteBuilder.MapControllerRoute
Cú pháp cơ bản đó là:
MapControllerRoute(string name, string pattern, object defaults = null, object constraints = null);name tên của route. pattern mẫu URL. defaults giá trị mặc định cho route. constraints là các ràng buộc
Ví dụ:
/... app.UseRouting(); // Tạo các Endpoint app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); /...Đoạn code trên đã tạo ra một Route ánh xạ URL vào Controller, mẫu này xác định trong pattern đó là URL với cấu trúc {controller=Home}/{action=Index}/{id?} nghĩa URL phù hợp mẫu có ba phần /controller/action/id phần thứ nhất tương ứng với tên Controller (tên lớp trong thư mục Controllers, ví dụ này là HomeController), phần thứ 2 biến action - là Action trong Controller (tên phương thức), phần thứ 3 là một tham số tên biến id (tham số này có dấu ? có nghĩa là có thể có hoặc không - tùy chọn)
Như vậy nếu truy cập địa chỉ /Home/Index thì có nghĩa sẽ tham chiếu đến lớp HomeController, gọi đến action (phương thức) Index của nó.
Tất nhiên, sẽ thêm được nhiều endpoint ánh xạ URL, khi truy vấn đến nó so sánh từ trên xuống, gặp cái nào phù hợp sẽ chuyển thi hành controller/action tương ứng. Ví dụ:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapControllerRoute( name: "myroute", defaults: new {controller="Home", action = "Index"}, pattern: "{title}-{id}.html"); });Ở Route tên myroute phù hợp khi truy cập URL dạng /tieude-134.html, ROUTE này không chỉ rõ Controller, Action trong pattern mà chỉ ra trong defaults như trên. Các Url phù hợp đều dẫn đến thi hành HomeController::Index
Tạo ràng buộc trong Route - URL
Với mỗi biến trong Route (như controller, action, id, title ...) có thể khống chế phải phù hợp với điều kiện nào đó, thường những điều kiện là biểu thức chính quy (RegEx - xem biểu thức chính quy). Ví dụ như Route có tên myroute sau đây:
/.. app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapControllerRoute( name: "myroute", // đặt tên route defaults: new {controller="Home", action = "Index"}, constraints: new { id = @"\d+", // id phải có và phải là số title = new RegexRouteConstraint(new Regex(@"^[a-z0-9-]*$")) // title chỉ chứa số, chữ thường và ký hiệu - }, pattern: "{title}-{id}.html"); }); /..Bạn cũng có thể viết các dàng buộc trực tiếp trong pattern (xem thêm ở EndpointMiddleware đọc kỹ phần ràng buộc), các dàng buộc tham khảo tại route-constraint-reference ), ví dụ:
endpoints.MapControllerRoute ( name: "myroute", // đặt tên route defaults : new { controller = "Home", action = "Index" }, pattern: "{title:alpha:maxlength(8)}-{id:int}.html"); // title chỉ chứa các chữ cái, dài tối đa 8, id là số nguyênTạo Controller trong ASP.NET MVC
Controller có chức năng nhận Request gửi đến và trả về Response. ASP.NET MVC thì các Controller lưu trong thư mục Controllers, đồng thời các lớp controller đặt tên có hậu tố là Controller, ví dụ *Controller, như trong ứng dụng đã tạo ra có sẵn lớp HomeController
Thông thường các controller kế thừa từ lớp Controller, sau đó khai báo các phương thức có thể được gọi khi Route ánh xạ đến gọi là Action
public class HomeController : Controller { /... public IActionResult Index() { return View(); } /... }Các Action
Controller có các phương thức gọi là Action, như trên action Index nó trả về IActionResult, thực tế nó có thể trả về bất kỳ kiểu dữ liệu nào. Ví dụ:
/... public string XinChao() => "Xin chào ASP.NET Core 3.0"; /...Truy cập địa chỉ /Home/XinChao thấy dòng text trên.
Trong Controller có sẵn các phương thức trả về các kiểu triển khai từ IActionResult như:
Kiểu trả về | Phương thức ------------------------------------------------ ContentResult | Content() EmptyResult | new EmptyResult() FileResult | File() ForbidResult | Forbid() JsonResult | Json() LocalRedirectResult | LocalRedirect() RedirectResult | Redirect() RedirectToActionResult | RedirectToAction() RedirectToPageResult | RedirectToRoute() RedirectToRouteResult | RedirectToPage() PartialViewResult | PartialView() ViewComponentResult | ViewComponent() StatusCodeResult | StatusCode() ViewResult | View()Action trả về ContentResult
Lớp ContentResult là mở rộng của ActionResult, nó cho phép bạn tạo ra nội dung tài liệu trả về trong Action. Để tạo ra đối tượng ContentResult cần khởi tạo nó với ba tham số gồm: nội dung tài liệu, kiểu tài liệu và encoding của tài liệu
Ví dụ, trả về một nội dung văn bản:
/... public IActionResult GetContent () { // mime - tham khảo https://en.wikipedia.org/wiki/Media_type string contentType = "text/plain"; string content = "Đây là nội dung file văn bản"; return Content (content, contentType, Encoding.UTF8); } /...Action trả về JsonResult
Phương thức Json của Controller trích xuất các thuộc tính của đối tượng và chuyển thành Json, Response trả về có header Content-Type application/json
/... public IActionResult GetJson() { return Json( new { key1 = 100, key2 = new string[] {"a", "b", "c"} } ); } /...Truy cập địa chỉ /Home/GetJson kết quả
{"key1":100,"key2":["a","b","c"]}Chuyển hướng truy cập
Có một số phương thức để chuyển hướng, thường có tiền tố Redirect, ví dụ vài phương thức như:
public IActionResult TestRedirect() { return Redirect("https://xuanthulab.net"); // Redirect 302 - chuyển hướng sang URL khác // return RedirectToRoute(new {controller="Home", action="Index"}); // Redirect 302 - Found // return RedirectPermanent("https://xuanthulab.net"); // Redirect 301 - chuyển hướng URL khác // return RedirectToAction("Index"); // Chuyển hướng sang Action khác }Trả về nội dung file
Phương thức File, tùy ngữ cảnh nó trả về nội dung file.
/... public IActionResult FileAnh() { string filepath = "logo.png"; return File(filepath, "image/png"); } /...Trả về 404 - NotFound
/... public IActionResult KhongCoGi() { return NotFound( "Trang không thấy" ); } /...Sử dụng tham số cho Action
Có thể khai báo các Action có tham số, các tham số này được truyền thiết lập qua biến trong Route hay trong Url Query
/... public IActionResult Sum(int x, int y) { return Content((x+y).ToString(), "text/plain", Encoding.UTF8); } /...Truy cập /Home/Sum?x=10&y=100 trả về nội dung 110
Trong lớp Controller còn có các thuộc tính truy cập nhiều loại thông tin rất đa dạng, những thuộc tính này sẽ tìm hiểu dần ở các phần sau như:
- HttpContext - thuộc tính này giúp lấy được ServiceProvider của ứng dụng.
- Request
- Response
- RouteData - dữ liệu Route
- ViewBag và ViewData - giúp chuyển dữ liệu đến View
- TempData - giúp chia sẻ dữ liệu giữa các phiên
- User
Tạo View trong ASP.NET MVC - Razor View Engine
View kết hợp với dữ liệu nó nhận được, phát sinh nội dung HTML trả về cho client. Các View (file .cshtml) được bố trí trong thư mục Views, nó là các template - là các file có phần mở rộng .cshtml, trong đó nó chứa mã HTML, đồng thời nhúng mã C# (server side script), những đoạn nhúng mã server side thì bắt đầu bằng ký hiệu @
View là các file .cshtml sử dụng cú pháp Razor, thực tế trong ứng dụng mô hình MVC có áp dụng lại cả các trang Razor Page hoàn chỉnh, nên bạn cần hiểu rõ về Razor Page đã trình bày ở phần trước, ví dụ như Cú pháp Razor, Layout Razor ...
Nhiệm vụ của View là xuất HTML, trong NET Core có thành phần gọi là Razor View Engine (từ đây gọi là Razor), nó có nhiệm vụ đọc các file View, thi hành các mã nhúng rồi xuất ra HTML.
Khi một Action trả về đối tượng ViewResult (phương thức View của Controller tạo ra loại đối tượng này). Thì nó sẽ sử dụng View .cshtml và Razor làm việc để tạo nội dung HTML. Nó sẽ tìm đến thư mục Views, tìm đến thư mục cùng tên Controller ví dụ Home, sau đó là file .cshtml cùng tên với Action - file .cshtml tìm được sẽ sinh HTML.
Nếu vậy:
public class HomeController : Controller { /... public IActionResult Index() { return View(); // Trả về ViewResult } /... }Action trên sẽ sử dụng View tương ứng là Views/Home/Index.cshtml, hãy biên tập nội dung file thành:
@{ Layout = null; } <!doctype html> <html> <head> <title>Trang View đầu tiên</title> </head> <body> <p>View .CSHTML là template <strong>Razor</strong> - nó chứa code C# bắt đầu bởi @@</p> <p><i>@DateTime.Now.ToLongDateString()</i></p> </body> </html>Để chèn một dòng code server side, thì sử dụng @ sau đó là dòng code, Razor tự nhận biết được đoạn kết thúc hết code khi phát hiện thẻ HTML, như ví dụ trên
<p><i>@DateTime.Now.ToLongDateString() xuanthulab.net</i></p>Để mở khối thì sử dụng thêm { ... }
@{ //code C# }Thêm thư mục lưu trữ các View .cshtml
Các View cho các Action mặc định lưu theo cấu trúc thư mục /View/ControllerName/ActionName.cshtml, nếu muốn thay đổi hoặc thêm cấu trúc mới thì thiết lập cho RazorEngine ở Startup.ConfigureService, ví dụ:
// • {0} - Action Name // • {1} - Controller Name // • {2} - Area Name // • RazorViewEngine.ViewExtension - .cshtml services.Configure<RazorViewEngineOptions>(options => { // Tìm thêm View ở /MyView/ControllerName/ActionName.cshtml options.ViewLocationFormats.Add("/MyView/{1}/{0}" + RazorViewEngine.ViewExtension); });Truyền dữ liệu Controller tới View với ViewBag
Để truyền dữ liệu trong MVC, bạn có thể sử dụng:
- Thiết lập Model cho View, khi gọi phương thức View của Controller. Trong View .cshtml sử dụng chỉ thị @model để thiết lập kiểu truyền tới cho Model của View
- Sử dụng property ViewData của View và Controller
- Sử dụng ViewBag của View và Controller
- Sử dụng TemData truyền dữ liệu giữa các trang (dùng cookie)
Để truyền dữ liệu từ Controller sang View, trong Controller có thể sử dụng thuộc tính ViewBag, đây là kiểu Dynamic, có thể thiết lập dữ liệu vào nó với cặp key/value
public IActionResult Index() { ViewBag.dulieu1 = "Đây là dữ liệu 1"; //key=dulieu1, value = "Đây là dữ liệu 1" ViewBag.dulieu2 = 12345; return View(); }Khi controller thiết lập dữ liệu qua ViewBag, thì ở View truy cập được thuộc tính này của Controller với ký hiệu @, đó là:
@ViewBag.key @{ Layout = null; } <!doctype html> <html> <head> <title>Trang View đầu tiên</title> </head> <body> <p>View .CSHTML là template <strong>Razor</strong> - nó chứa code C# bắt đầu bởi @@</p> <p><i>@DateTime.Now.ToLongDateString()</i></p> <p>@ViewBag.dulieu1</p> <p>@ViewBag.dulieu2</p> </body> </html>Truyền dữ liệu Controller tới View với Model
Trong Razor có một thuộc tính có tên Model thuộc tính này là một kiểu gereric (trong cú pháp ký hiệu nó là TModel, xem thêm Generic trong C# , TModel thực tế là kiểu gì được quyết định khi khởi tạo ViewResult)
Từ Controller, khi khởi tạo ViewResult với phương thức View, bạn có thể chỉ ra tham số chính là Model, ví dụ:
return View(ModelObject); // ModelObject là đối tượng bất kỳ - nó là Model trong RazorLúc này, trong .phtml, Razor sẽ đọc được qua thuộc tính với tên Model - Ví dụ:
public IActionResult Index() { ViewBag.dulieu1 = "Đây là dữ liệu 1"; ViewBag.dulieu2 = 12345; // Một danh sách tênn các sản phầm List<string> sanpham = new List<string>() { "Bàn ăn", "Giường ngủ", "Tủ áo" }; // sanpham gán vào Model tronng Razor // Đã trả về ViewResult kèm dữ liệu return View(sanpham); }Lúc này ở View, Razor có thể truy cập được nó thông qua thuộc tính Model, nhưng ở phần đầu cần khai báo kiểu Model này với @model List<string>
@model List<string> @{ Layout = null; } <!doctype html> <html> <head> <title>Trang View đầu tiên</title> </head> <body> <p>View .CSHTML là template <strong>Razor</strong> - nó chứa code C# bắt đầu bởi @@</p> <p><i>@DateTime.Now.ToLongDateString() xuanthulab.net</i></p> <p>@ViewBag.dulieu1</p> <p>@ViewBag.dulieu2</p> <ol> @foreach (var sp in Model) { <li>@sp</li> } </ol> </body> </html>@model là một chỉ thị của Razor, nó cho biết kiểu của Model, cú pháp khai báo là @model Kiểu_Của_Model
Phát sinh controller, view, razor page, area
aspnet-codegenerator là công cụ bổ sung vào lệnh dotnet nó trợ giúp phát sinh nhanh các cấu trúc thư mục chuẩn, tạo controller, view, razor page nhanh hơn, tránh những thao tác đơn giả bạn phải làm thủ công.
Đảm bảo cài đặt công cụ lệnh dotnet aspnet-codegenerator
dotnet tool install -g dotnet-aspnet-codegenerator dotnet tool update -g dotnet-aspnet-codegeneratorThêm package
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.DesignGõ lệnh để xem hướng dẫn
dotnet aspnet-codegenerator -hTạo một Area
Area là khu vực (thư mục) gom các Controller, Razor page thành nhóm (xem Area)
Để tạo ra cấu trúc thư mục cho một Area nào đó gõ lệnh:
dotnet aspnet-codegenerator NameAreaNó sẽ tạo thư mục Areas/NameArea/ và trong nó là các thư mục con theo chuẩn như: Controller, View, Models ...
Tạo ra Controller
Tạo một controller tên First mã nguồn lưu ở thư mục Controllers
dotnet aspnet-codegenerator controller -name First -outDir ControllersNó sẽ tạo ra lớp FirstController trong thư mục Controllers
Tạo View
Tạo ra View đặt tên Index, mẫu tạo là Empty, kết quả lưu tại Views/First sử dụng layout là _Layout
dotnet aspnet-codegenerator view Index Empty -outDir Views/First -l _Layout -fCác lệnh trên nó còn phát sinh làm việc với với các Model, tạo các trang CRUD - tuy nhiên cần tích hợp dự án với DbContext, sẽ nói ở các phần khác
Mã nguồn ví dụ ASP_NET_CORE/mvc01_HelloWorld hoặc tải về ex053
Mục lục bài viết Tạo ứng dụng ASP.NET MVCSSL - kích hoạt https ASP.NET CoreRoute ASP.NET MVCTạo Controller ASP.NET MVCTạo View ASP.NET MVCTruyền dữ liệu Controller tới View với ViewBagTruyền dữ liệu Controller tới View với ModelPhát sinh mã, cấu trúc với aspnet-codegenerator ĐĂNG KÝ KÊNH, XEM CÁC VIDEO TRÊN XUANTHULAB Đăng ký nhận bài viết mới Lớp Uri Dns Ping và các lớp về Networking trong lập trình C# NET Core Code C# chuyển số thành chữ (ASP.NET Core) Sử dụng gulp.js build SCSS (SASS) thành CSS (ASP.NET Razor) Chứng thực quyền của User theo RoleClaim (ASP.NET Razor) Các trang quản lý tài khoản cá nhân trong Identity (EF Core) Tạo migration trong EntityFramework với C# CSharp (EF Core) Sinh ra các entity từ database với công cụ dotnet ef trong C# CSharp (EF Core) Thực hiện các câu truy vấn với Entity Framework C# CSharp (EF Core) Tạo quan hệ trong Entity Framework với Fluent API C# CSharp (EF Core) Tạo Model trong Entity Framework ánh xạ các đối tượng vào Database C# CSharp (ASP.NET RAZOR) IAuthorizationService (Bài trước) (Bài tiếp) (ASP.NET MVC) Route Giới thiệuPrivacyTừ điển Anh - ViệtChạy SQLRegExpCubic-bezierUnix timestampKý tự HTMLcalories, chỉ số BMRchỉ số khối cơ thể BMITạo QR CodeLịch vạn niên Liên hệ RSSĐây là blog cá nhân, tôi ghi chép và chia sẻ những gì tôi học được ở đây về kiến thức lập trình PHP, Java, JavaScript, Android, C# ... và các kiến thức công nghệ khác Developed by XuanThuLab
Từ khóa » Tự Học Asp.net Mvc
-
Tải Ngay Giáo Trình Mvc Miễn Phí Tự Học Tại Nhà - CodeGym
-
Tự Học ASP.NET MVC 5 - Thư Viện Lập Trình
-
Bài 1: Giới Thiệu ASP.NET MVC Và Tạo ứng Dụng ASP.NET ... - TEDU
-
Hướng Dẫn Tự Học Lập Trình ASP.NET Core Toàn Tập
-
Hướng Dẫn Học Lập Trình ASP.NET MVC 5 Thiết Kế Website Bán Hàng
-
ASP.NET MVC | Từ Coder đến Developer – Tôi đi Code Dạo
-
[Khóa Học Lập Trình ASP.Net MVC 5 Cơ Bản] - Bài 1 - YouTube
-
Lập Trình ASP.NET MVC - Bài 1 - YouTube
-
ASP.NET MVC | Advanced Programming
-
Lập Trình Website Với ASP.Net MVC Cơ Bản | How Kteam
-
Lập Trình Web Application Với ASP.NET MVC Web API | .vn
-
Tự Học ASP.NET MVC | DAMMIO
-
ASP.NET MVC Cơ Bản | DAMMIO
-
Lập Trình Web Với ASP.NET MVC5 | DEVMASTER