Thứ Năm, 14 tháng 1, 2016

VÍ DỤ VỀ MVC

 By   
MVC (Model – View – Controller) là là một kiến trúc phần mềm hay mô hình thiết kế được sử dụng trong kỹ thuật phần mềm. Hôm nay mình sẽ giới thiệu cho các bạn về mô hình MVC trong ASP .Net và tạo một project  nhỏ để minh họa cho mô hình này. 
I. MÔ HÌNH MVC LÀ GÌ?
MVC là chữ viết tắt của Model – View – Controller, đây là một mô hình kiến phần mềm được tạo ra với mục đích quản lý và xây dựng dự án phần mềm có hệ thống hơn. Mô hình này được dùng khá rộng rãi và đặc biệt là trong các ngôn ngữ lập trình web. Trong .NET cũng hỗ các framework để lập trình theo mô hình này.
Trong mô hình này thì:
  • Model: có nhiệm vụ thao tác với cơ sở dữ liệu, nghĩa là nó sẽ chứa tất cả các hàm, các phương thức truy vấn trực tiếp với dữ liệu và controller sẽ thông qua các hàm, phương thức đó để lấy dữ liệu rồi gửi qua View
  • View: có nhiệm vụ tiếp nhận dữ liệu từ controller và hiển thị nội dung sang các đoạn mã HTML, bạn có thể hiểu nôm na đây người ta còn gọi là thành phần giao diện.
  • Controller: đóng vài trò trung gian giữa ModelView. Nó có nhiệm vụ tiếp nhận yêu cầu từ client sau đó xử lý request, loadmodel tương ứng và gửi data qua view tương ứng rồi trả kết quả về cho client.
[img]http://i.imgur.com/R1EHYks.png[/img]
II. TẠO PROJECT ASP .NET MCV 4 RAZOR
Chúng ta sẽ tạo một website đơn giản quản lý sản phẩm, gồm 2 trang, một trang xem tất cả sản phẩm và một trang tạo mới sản phẩm, ở trang xem sản phẩm có nút tạo sản phẩm để chuyển qua trang tạo mới sản phẩm, ngoài ra có thêm mục xóa để xóa sản phẩm.
[img]http://i.imgur.com/R1EHYks.png[/img]
[img]http://i.imgur.com/R1EHYks.png[/img]
Cơ sỡ dữ liệu sẽ đơn giản như sau:
[img]http://i.imgur.com/R1EHYks.png[/img]
Và ta có thể hình dung hoạt động của website như bên dưới
[img]http://i.imgur.com/R1EHYks.png[/img]
Bước 1: Mở visual studio chọn File -> New -> Project…  Sau đó tìm chọn như hình bên dưới.
[img]http://i.imgur.com/R1EHYks.png[/img]
[img]http://i.imgur.com/R1EHYks.png[/img]
Bước 2: Ta sẽ dùng Entity Framework Code First để tạo cơ sở dữ liệu, các bạn xem thêm về Entity Framework tại đây
Các bạn lần lượt tạo các class sau trong thư mục Models của project chúng ta vừa tạo (click chuột phải vào thư mục Models chọn Add -> Class…)
Class Category cho bảng Category
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.DataAnnotations;
  4. using System.ComponentModel.DataAnnotations.Schema;
  5. using System.Linq;
  6. using System.Web;

  7. namespace MVCExample.Models
  8. {
  9. [Table("CATEGORIES")]
  10. public class Category
  11. {
  12. [Key]
  13. public int IDCategory { set; get; }
  14. public string Name { set; get; }
  15. public virtual ICollection Products { set; get; }
  16. }
  17. }
Class Product cho bảng Product
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.DataAnnotations;
  4. using System.ComponentModel.DataAnnotations.Schema;
  5. using System.Linq;
  6. using System.Web;

  7. namespace MVCExample.Models
  8. {
  9. [Table("PRODUCTS")]
  10. public class Product
  11. {
  12. [Key]
  13. public int IDProduct { set; get; }
  14. public int IDCategory { set; get; }
  15. public string Name { set; get; }
  16. public string SeriNumber { set; get; }
  17. public string Country { set; get; }
  18. [ForeignKey("IDCategory")]
  19. public virtual Category Category { set; get; }
  20. }
  21. }
Class DataContext để tạo cơ sở dữ liệu
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Linq;
  5. using System.Web;

  6. namespace MVCExample.Models
  7. {
  8. public class DataContext:DbContext
  9. {
  10. public DbSet Categories { set; get; }
  11. public DbSet Products { set; get; }
  12. public DataContext()
  13. : base("mydata")//Tên của chuỗi kết nối
  14. {
  15. //Tạo cơ sỡ dữ liệu nếu chưa có
  16. Database.SetInitializer(new DataInitializer());
  17. }
  18. public class DataInitializer : CreateDatabaseIfNotExists
  19. {
  20. protected override void Seed(DataContext context)
  21. {
  22. //Ta thêm một số dữ liệu mẫu cho cơ sở dữ liệu
  23. context.Categories.Add(new Category { Name = "Xe đạp" });
  24. context.Categories.Add(new Category { Name = "Xe máy" });
  25. context.Categories.Add(new Category { Name = "Xe hơi" });
  26. context.Products.Add(new Product { IDCategory = 1, Name = "Matin",
  27. SeriNumber = "283y52398hf9u2yr", Country = "Việt Nam" });
  28. context.Products.Add(new Product { IDCategory = 1, Name = "Kasama",
  29. SeriNumber = "283yrh45h45j49u2yr", Country = "Việt Nam" });
  30. context.Products.Add(new Product { IDCategory = 2,
  31. Name = "Future neo 125", SeriNumber = "283y5sdgwegf9u2yr", Country = "Việt Nam" });
  32. base.Seed(context);
  33. }
  34. }
  35. }
  36. }
Các bạn đừng quên sửa lại chuỗi kết nối ở file web.config nhé
  1. "mydata" connectionString="Data Source=TenServerSQLCuaBan;Initial Catalog=MVCExample;Integrated Security=true;" providerName="System.Data.SqlClient" />
Bước 3: Tạo các trang View
Các bạn click chuột phải vào thư mục View sau đó chọn Add -> New Folder, các bạn đặt tên folder là “ProductsManagements
Sau đó click chuột phải vào thư mục vừa tạo chọn Add -> New Item… Các bạn tìm chọn MVC 4 View Page (Razor) rồi đặt tên cho trang View của mình và click Add. Chúng ta sẽ tạo 2 trang View có tên lần lượt là AddProductViewProducts
[img]http://i.imgur.com/R1EHYks.png[/img]
Bước 4: Tạo Controller
Sau khi tạo xong các trang View, ta tạo tiếp controller để điều hướng cho các trang view này, các bạn click chuột phải vào thư mục Controllers và chọn Add -> Controller… các bạn đặt tên cho controller này là “ProductsManagementsController”. Chú ý là tên controller với phần bôi đỏ phải trùng với tên thư mục chứa các trang view mà controller này sẽ điều hướng.
Bước 5: Viết code (mình có giải thích cụ thể trong code nhé)
Khi sử dụng Razor, để chèn mã code C# vào mã HTML, chúng ta sử dụng ký tự @ trước mã C#
Đầu tiên, để hiển thị trang ViewProducts lên Client, chúng ta cần một phương thức làm việc điều hướng tới trang này trong Controller, tại phương thức này ta cũng tiến hành lấy danh sách các Product để trả về cho Client.
Và để tương tác với cơ sở dữ liệu, ta khai báo đối tượng datacontext thuộc Lớp DataContext của phần Model trong class ProductsManagementsController
  1. DataContext datacontext = new DataContext();
Ta viết phương thức trả về trang ViewProducts trong file ProductsManagementsController như sau:
  1. public ActionResult ViewProducts()
  2. {//Phương thức này trả về trang ViewProducts cho client
  3. ViewBag.Products = datacontext.Products.ToList();
  4. //Chúng ta dùng ViewBag để chứa danh sách Products trong cơ sở dữ liệu
  5. //phần .Products sau ViewBag là do chúng ta tự đặt
  6. return View();
  7. //Trường hợp trang View cúng ta muốn trả về client trùng tên với tên phương thức thì phương thức View chúng ta không đưa tham số vào
  8. }
Chúng ta có trang ViewProducts như sau:
  1. @{
  2. ViewBag.Title = "ViewProducts";
  3. }
  4. @using MVCExample.Models;
  5. ViewProducts

  6. "1">
  7. "font-weight:bold">
  8. ID
  9. Category
  10. Name
  11. Seri Number
  12. Country
  13. Delete
  • @foreach (Product P in ViewBag.Products)
  • {// ViewBag ở đây có thể hiểu như request trong java vậy, và trong trường hợp này
  • //ViewBg chứa danh sách các Product được lấy trong cơ sở dữ liệu và được truyền về từ server
  • @P.IDProduct
  • @P.Category.Name
  • @P.Name
  • @P.SeriNumber
  • @P.Country
  • "/ProductsManagements/DeleteProduct?IDProduct=@P.IDProduct">Delete
  • }

  • "/ProductsManagements/ViewAddProduct">"button" value="Add Product" />
  • Tại trang ViewProducts, ta có thể tiến hành xóa một product bằng cách click vào nút delete tương ứng, và việc này sẽ gọi đến controller ProductsManagementsController, Controller sẽ tìm đến phương thức DeleteProduct với tham số truyền vào và IDProduct để tiến hành xóa 1 products. Do đó ta có phương thức DeleteProduct như sau:
    1. public ActionResult DeleteProduct(string IDProduct)// tên tham số phải trùng với tên tham số truyền ở client
    2. {// Phương thức này xóa một product có id là IDProduct, tham số này được truyền đến từ client
    3. try
    4. {
    5. int ID = Convert.ToInt32(IDProduct);
    6. new Product().DeleteProduct(ID);// gọi phương thức xóa product của lớp Product tren tầng model
    7. return RedirectToAction("ViewProducts");
    8. //Cái này có thể hiểu nôn na là nó sẽ gọi phương thức có tên ViewProducts để thực hiện
    9. }
    10. catch
    11. {
    12. return View("Error");
    13. }
    14. }
    Ở đây ta thấy rằng Controller chỉ đóng vai trò điều hướng, nên việc thay đổi cơ sở dữ liệu phải để tầng Model thực hiện, cụ thể ở đây ta có gọi phương thức DeleteProduct của lớp Product, do đó ta bổ sung phương thức này vào class Product
    1. //Hàm dùng để xóa 1 product theo id khi controller gọi đến
    2. public void DeleteProduct (int ID){
    3. DataContext datacontext = new DataContext();
    4. Product P = datacontext.Products.SingleOrDefault(x => x.IDProduct == ID);
    5. //Lấy product có id ddwwocj truyền vào từ cơ sở dữ liệu ra
    6. if (P != null)
    7. {//nếu lấy được thì tiến hành xóa
    8. datacontext.Products.Remove(P);
    9. datacontext.SaveChanges();
    10. }
    11. }
    Cũng tại trang ViewProducts, ta cũng có thể chọn việc thêm một Product bằng cách click vào button Add Product, khi click vào button này sẽ gọi đến controller ProductsManagementsController, Controller
    sẽ tìm đến phương thức ViewAddProduct và trả về trang View AddProducts lên trình duyệt, tại phương thức này ta cũng tiến hành lấy danh sách các Category để đưa về client phục vụ cho việc người dùng chọn lựa. Ta thêm phương thức này vào Controller
    1. public ActionResult ViewAddProduct()
    2. {//phương thức này trả về trang view AddProduct
    3. ViewBag.Categories = datacontext.Categories.ToList();
    4. //Tương tự ta dùng ViewBag để chứa danh sách Category trả về cho Client
    5. return View("AddProduct");
    6. //Trường hợp trang View cúng ta muốn trả về client không trùng tên với tên phương thức thì phương thức View chúng ta đa vào tham số là tên trang view chúng ta muốn trả về
    7. }
    Trang AddProduct
    1. @{
    2. ViewBag.Title = "AddProduct";
    3. }
    4. @using MVCExample.Models;
    5. AddProduct

    6. @using (Html.BeginForm("AddProduct", "ProductsManagements", FormMethod.Post, new { name = "PM" }))
    7. {// Đây là câu lệnh tạo form, cái này cũng giống như thẻ
      trong HTML, form này có tên là PM
    8. // và khi submit, nó sẽ gọi đến Controller ProductsManagements để tìm đến hàm AddProduct và tiến hành đưa dữ liệu vào cơ sử dữ liệu
    9. Name:
    10. "text" name="Name"/>
  • Category:
  • @foreach (Category C in ViewBag.Categories)
  • {// ViewBag ở đây có thể hiểu như request trong java vậy, và trong trường hợp này
  • //ViewBg chứa danh sách các Category được lấy trong cơ sở dữ liệu và được truyền về từ server
  • }
  • Seri Number:
  • "text" name="Seri" />
  • Country:
  • "text" name="Country" />
  • "submit" value="Add"/>
  • }
  • Khi click vào nút Add, nó sẽ gọi đến Controller ProductsManagements để tìm đến phương thức AddProduct, tại phương thức này, ta sẽ lấy dữ liệu từ các control của form và thêm vào cơ sở dữ liệu, ta thêm vào controller phương thức sau
    1. public ActionResult AddProduct(FormCollection form)
    2. {//Phương thức thêm một product và cơ sở dữ liệu
    3. // đối tượng của LỚp FormCollection sẽ lấy giá trị value của tất cả các control có thuộc tính name
    4. // trên form gọi đến phương thức này
    5. Product P = new Product();
    6. P.IDCategory = Convert.ToInt32(form["Category"]);
    7. P.Name = form["Name"];// lấy giá trị của thẻ input có tên là Name
    8. P.SeriNumber = form["Seri"];
    9. P.Country = form["Country"];
    10. datacontext.Products.Add(P);
    11. datacontext.SaveChanges();
    12. return RedirectToAction("ViewProducts");
    13. }
    Gộp lại ta sẽ có mã nguồn file Controller và class Product như sau
    1. using MVCExample.Models;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Web;
    6. using System.Web.Mvc;

    7. namespace MVCExample.Controllers
    8. {
    9. public class ProductsManagementsController : Controller
    10. {
    11. //
    12. // GET: /ProductsManagement/
    13. DataContext datacontext = new DataContext();
    14. public ActionResult ViewProducts()
    15. {//Phương thức này trả về trang ViewProducts cho client
    16. ViewBag.Products = datacontext.Products.ToList();
    17. //Chúng ta dùng ViewBag để chứa danh sách Products trong cơ sở dữ liệu
    18. //phần .Products sau ViewBag là do chúng ta tự đặt
    19. return View();
    20. //Trường hợp trang View cúng ta muốn trả về client trùng tên với tên phương thức thì phương thức View chúng ta không đưa tham số vào
    21. }
    22. public ActionResult ViewAddProduct()
    23. {//phương thức này trả về trang view AddProduct
    24. ViewBag.Categories = datacontext.Categories.ToList();
    25. //Tương tự ta dùng ViewBag để chứa danh sách Category trả về cho Client
    26. return View("AddProduct");
    27. //Trường hợp trang View cúng ta muốn trả về client không trùng tên với tên phương thức thì phương thức View chúng ta đa vào tham số là tên trang view chúng ta muốn trả về
    28. }
    29. public ActionResult AddProduct(FormCollection form)
    30. {//Phương thức thêm một product và cơ sở dữ liệu
    31. // đối tượng của LỚp FormCollection sẽ lấy giá trị value của tất cả các control có thuộc tính name
    32. // trên form gọi đến phương thức này
    33. Product P = new Product();
    34. P.IDCategory = Convert.ToInt32(form["Category"]);
    35. P.Name = form["Name"];// lấy giá trị của thẻ input có tên là Name
    36. P.SeriNumber = form["Seri"];
    37. P.Country = form["Country"];
    38. datacontext.Products.Add(P);
    39. datacontext.SaveChanges();
    40. return RedirectToAction("ViewProducts");
    41. }
    42. public ActionResult DeleteProduct(string IDProduct)// tên tham số phải trùng với tên tham số truyền ở client
    43. {// Phương thức này xóa một product có id là IDProduct, tham số này được truyền đến từ client
    44. try
    45. {
    46. int ID = Convert.ToInt32(IDProduct);
    47. new Product().DeleteProduct(ID);// gọi phương thức xóa product của lớp Product tren tầng model
    48. return RedirectToAction("ViewProducts");
    49. //Cái này có thể hiểu nôn na là nó sẽ gọi phương thức có tên ViewProducts để thực hiện
    50. }
    51. catch
    52. {
    53. return View("Error");
    54. }
    55. }
    56. }
    57. }
    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel.DataAnnotations;
    4. using System.ComponentModel.DataAnnotations.Schema;
    5. using System.Linq;
    6. using System.Web;

    7. namespace MVCExample.Models
    8. {
    9. [Table("PRODUCTS")]
    10. public class Product
    11. {
    12. [Key]
    13. public int IDProduct { set; get; }
    14. public int IDCategory { set; get; }
    15. public string Name { set; get; }
    16. public string SeriNumber { set; get; }
    17. public string Country { set; get; }
    18. [ForeignKey("IDCategory")]
    19. public virtual Category Category { set; get; }
    20. //Hàm dùng để xóa 1 product theo id khi controller gọi đến
    21. public void DeleteProduct (int ID){
    22. DataContext datacontext = new DataContext();
    23. Product P = datacontext.Products.SingleOrDefault(x => x.IDProduct == ID);
    24. //Lấy product có id ddwwocj truyền vào từ cơ sở dữ liệu ra
    25. if (P != null)
    26. {//nếu lấy được thì tiến hành xóa
    27. datacontext.Products.Remove(P);
    28. datacontext.SaveChanges();
    29. }
    30. }
    31. }
    32. }
    Để kiểm Chạy thử website, các bạn tìm đến thư mục App_Start, mở file RouteConfig.cs và sửa lại Controller cùng với action sẽ thực hiện khi lần đầu mở website như sau
    1. routes.MapRoute(
    2. name: "Default",
    3. url: "{controller}/{action}/{id}",
    4. defaults: new { controller = "ProductsManagements", action = "ViewProducts", id = UrlParameter.Optional }
    5. );
    Các bạn có thể tải project mẫu tại đây
    Cảm ơn các bạn đã theo dõi bài viết

    0 nhận xét: