Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 44 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
44
Dung lượng
2,1 MB
Nội dung
CHƯƠNG SportsStore: Một ứng dụng thực tế Trong chương trước, xây dựng ứng dụng MVC nhanh đơn giản Tơi mơ tả mơ hình MVC, tính C# thiết yếu loại cơng cụ mà nhà phát triển MVC yêu cầu Bây lúc để đưa thứ lại với xây dựng ứng dụng thương mại điện tử đơn giản thực tế Ứng dụng tôi, gọi SportsStore, theo phương pháp cổ điển thực cửa hàng trực tuyến nơi Tôi tạo danh mục sản phẩm trực tuyến mà khách hàng duyệt theo thể loại theo trang, giỏ mua hàng, mà người dùng thêm loại bỏ sản phẩm, checkout, nơi khách hàng nhập chi tiết giao hàng họ Tôi tạo vùng administration bao gồm việc tạo - Create, đọc - Read, cập nhật Update, xóa - Delete (CRUD) thuận tiện cho việc quản lý danh mục; tơi bảo mật để có administrator đăng nhập chỉnh sửa Mục tiêu chương chương sau để cung cấp cho bạn cảm giác mà phát triển MVC Framework thực đem lại việc tạo ví dụ thực tế tốt Tôi muốn tập trung vào MVC Framework, tất nhiên, tơi đơn giản hóa việc tích hợp với hệ thống bên ngoài, chẳng hạn sở liệu, bỏ qua hoàn toàn thứ khác, chẳng hạn việc xử lý tốn Bạn thấy tơi chậm chút xây dựng lên cấp sở hạ tầng mà cần Chắc chắn, bạn có chức ban đầu xây dựng cách nhanh chóng với Web Forms, cách kéo thả control ràng buộc trực tiếp đến database UNIT TESTING (KIỂM TRA ĐƠN VỊ) Tôi tạo nên vấn đề lớn dễ dàng unit testing MVC, niềm tin unit testing phần quan trọng trình phát triển Bạn thấy điều chứng minh suốt phần sách tơi bao hàm chi tiết unit test kỹ thuật có liên quan đến tính MVC quan trọng Tơi biết khơng phải ý kiến phổ quát Nếu bạn không muốn unit test, khơng Đến cuối cùng, tơi phải nói hồn tồn testing, tơi đặt sidebar Nếu bạn không quan tâm đến unit test, bạn bỏ qua phần này, ứng dụng SportsStore hoạt động ổn Bạn không cần phải làm loại unit test để có tiện ích cơng nghệ ASP.NET MVC, tất nhiên, hỗ trợ testing lý cho việc áp dụng MVC Framework Hầu hết tính MVC tơi sử dụng cho ứng dụng SportsStore có chương riêng sau sách Thay lặp lại thứ đây, tơi nói với bạn chút để tạo cảm nhận cho ứng dụng ví dụ bạn đến chương khác cho kiến thức chuyên sâu Tôi nêu bước cần thiết để xây dựng ứng dụng, bạn thấy làm tính MVC khớp với Bạn nên đặc biệt ý tạo view Bạn nhận số kết khác bạn không làm theo ví dụ cách xác Mở đầu Bạn phải cài đặt Visual Studio bạn có ý định lập trình ứng dụng SportsStore máy bạn bạn đọc qua phần sách Bạn tải project SportsStore mà kèm với sách (có sẵn từ Apress.com) Tất nhiên bạn không cần phải làm theo Tôi cố gắng chụp hình danh sách dòng lệnh để bạn dễ dàng làm theo Tạo Solution Project Visual Studio Tôi tạo solution Visual Studio có chứa ba project Một project chứa domain model, ứng dụng MVC, thứ ba chứa unit test Để bắt đầu, tạo solution Visual Studio gọi SportsStore sử dụng template Blank Solution, mà bạn tìm thấy phần Other Project Types/Visual Studio Solutions Bên trái hộp thoại New Project, minh họa Hình 7-1 Nhấn nút OK để tạo solution Hình 7-1 Tạo solution Visual Studio Một solution Visual Studio phần chứa nhiều project Tơi u cầu ba project cho ứng dụng ví dụ tôi, mà mô tả Bảng 7-1 Bạn thêm project cách click phải vào mục Solution Solution Explorer chọn Add New Project từ menu pop-up Bảng 7-1 Ba Project SportsStore Tên Project Visual Studio Project Template Mục đích SportsStore.Domain Class Library Giữ đối tượng domain logic; thiết lập bền vững thông qua kho lưu trữ tạo với Entity Framework SportsStore.WebUI ASP.NET MVC Web Application (chọn Empty nhắc để chọn project template đánh dấu check vào mục MVC) Giử controller view; hoạt động UI cho ứng dụng SportsStore SportsStore.UnitTests Unit Test Project Giữ unit test cho project Tôi luôn chọn Empty cho template ASP.NET MVC Web Application Các lựa chọn khác thêm thiết lập ban đầu cho project bao gồm: thư viện JavaScript, kiểu CSS, lớp C # đề cấu hình tính ứng dụng bảo mật routing Khơng có xấu - số thư viện mã nguồn mở mà Microsoft đem gần project tuyệt vời-nhưng bạn tự thiết lập tất nội dung cấu hình, làm vậy,ta tìm hiểu thêm hoạt động MVC Framework Khi bạn tạo ba project, Solution Explorer giống Hình 7-2 Tơi xóa file Class1.cs mà Visual Studio thêm vào project SportsStore.Domain Vì tơi khơng sử dụng Hình 7-2 Ba projects thể cửa sổ Solution Explorer Để debug dễ dàng hơn, chuột phải vào project SportsStore.WebUI chọn Set as Startup Project từ menu pop-up (bạn thấy tên chuyển sang in đậm) Điều nghĩa bạn chọn Start Debugging Start without Debugging từ menu Debug , project khởi động Visual Studio cố điều hướng đến file view cá nhân bạn chỉnh sửa chúng bạn khởi động debugger, click phải vào SportsStore.WebUI project Solution Explorer chọn Properties từ menu pop-up Click vào Web đề mở thuộc tính liên quan đến web chọn Specific Page Không cần nhập giá trị vào phần Specific Page Chỉ chọn lựa chọn đủ đề ngăn Visual Studio cố gắng đoán URL mà bạn muốn xem đảm bảo trình duyệt yêu cầu URL gốc cho ứng dụng bạn khởi động debugger Cài dặt gói cơng cụ (Tool Packages) Tơi sử dụng Ninject Moq chương Chọn Tools Library Package Manager Package Manager Console Visual Studio đề mở dòng lệnh NuGet nhập lệnh sau: Install-Package Ninject -version 3.0.1.10 -projectname SportsStore.WebUI Install-Package Ninject.Web.Common -version 3.0.0.7 projectname SportsStore.WebUI Install-Package Ninject.MVC3 -Version 3.0.0.6 projectname SportsStore.WebUI Install-Package Ninject -version 3.0.1.10 projectname SportsStore.UnitTests Install-Package Ninject.Web.Common -version 3.0.0.7 projectname SportsStore.UnitTests Install-Package Ninject.MVC3 -Version 3.0.0.6 projectname SportsStore.UnitTests Install-Package Moq -version 4.1.1309.1617 -projectname SportsStore.WebUI Install-Package Moq -version 4.1.1309.1617 projectname SportsStore.UnitTests Install-Package Microsoft.Aspnet.Mvc -version 5.0.0 projectname SportsStore.Domain Install-Package Microsoft.Aspnet.Mvc -version 5.0.0 projectname SportsStore.UnitTests - - Có nhiều lệnh NuGet để nhập tơi lựa chọn gói cài đặt vào project nào, chương trước, rõ phiên gói để tải xuống cài đặt Thêm References Project Tôi cần thiết lập phụ thuộc project số thành phần Microsoft Click phải vào project sổ Solution Explorer, chọn Add Reference, thêm reference thể Bảng 7-2 từ Assemblies Framework, Assemblies Extensions Solution Bảng 7-2 Sự phụ thuộc Project yêu cầu Solution phụ thuộc Tên Project SportsStore.Domain SportsStore.WebUI None SportsStore.Doma in SportsStore.Doma in SportsStore.UnitTes ts SportsStore.WebUI Assemblies References System.ComponentModel.DataAnnotat ions None System.Web Microsoft.CSharp Thận trọng Hãy dành thời gian để thiết lập mối quan hệ cách xác Nếu bạn khơng có thư viện project references đúng, bạn gặp vấn đề cố gắng build project Thiết lập DI Container Trong Chương 6, cho bạn thấy làm sử dụng Ninject để tạo phân giải phụ thuộc tùy chỉnh mà MVC Framework sử dụng để khởi tạo đối tượng thông qua ứng dụng Tơi lặp lại tiến trình đó, bắt đầu với việc thêm thư mục Infrastructure SportsStore.WebUI project thêm file class gọi NinjectDependencyResolver.cs Bạn thấy nội dụng file Listing 7-1 Listing 7-1 Nội dung file NinjectDependencyResolver.cs using using using using System; System.Collections.Generic; System.Web.Mvc; Ninject; namespace SportsStore.WebUI.Infrastructure { public class NinjectDependencyResolver : IDependencyResolver { private IKernel kernel; public NinjectDependencyResolver(IKernel kernelParam) { kernel = kernelParam; AddBindings(); } public object GetService(Type serviceType) { return kernel.TryGet(serviceType); } public IEnumerable GetServices(Type serviceType) { return kernel.GetAll(serviceType); } private void AddBindings() { // put bindings here } } } Như bạn nhớ lại từ Chương 6, bước tạo cầu nối lớp NinjectDependencyResolver MVC support cho việc chèn phụ thuộc file App_Start/NinjectWebCommon.cs, mà gói NuGet Ninject thêm vào project, Listing 7-2 Listing 7-2 Tích hợp Ninject file NinjectWebCommon.cs private static void RegisterServices(IKernel kernel) { System.Web.Mvc.DependencyResolver.SetResolver(new SportsStore.WebUI.Infrastructure.NinjectDependencyResolver(kernel) } Chạy thử ứng dụng Nếu bạn chọn Start Debugging từ menu Debug, bạn thấy trang bị lỗi Hình 7-3 Điều bạn request URL có liên quan với controller khơng tồn Hình 7-3 Trang bị lỗi Khởi động Domain Model Tất project MVC Framework bắt đầu với domain model tất thứ ứng dụng MVC Framework xoay quanh Vì ứng dụng thương mại điện tử, thực thể domain rõ ràng mà cần sản phẩm Tạo thư mục có tên gọi Entities bên project SportsStore.Domain sau tạo lớp C # tên Product.cs bên Bạn nhìn cấu trúc Hình 7-4 Hình 7-4 tạo lớp Product Bạn quen thuộc với định nghĩa lớp Product, tơi sử dụng mà bạn thấy chương trước Chỉnh sửa lớp Product.cs để giống Listing 7-3 Listing 7-3 Nội dung lớp Product.cs namespace SportsStore.Domain.Entities { public class Product { public int ProductID { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } public string Category { get; set; } } } Tôi làm theo kỹ thuật định nghĩa domain model project Visual Studio riêng biệt, có nghĩa lớp phải đánh dấu public Bạn không cần phải tuân theo quy tắc này, tơi thấy giúp giữ cho model riêng biệt với controller, điều hữu ích project lớn phức tạp Tạo Abstract Repository Tôi cần số cách để nhận thực thể Product từ database Như tơi giải thích Chương 3, model bao gồm việc luận lý học liên tục cho việc lưu trữ truy xuất liệu từ kho liệu liên tục, bên model Tôi muốn giữ mức độ tách biệt thực thể data model nơi lưu trữ truy xuất lôgic , mà đạt cách sử dụng repository pattern Tôi không lo lắng việc làm mà thực thi liệu liên tục chốc lát, bắt đầu trình xác định interface cho Tạo thư mục cấp cao bên project SportsStore.Domain tên Abstract bên thư mục mới, tạo file interface tên IProductsRepository.cs, nội dung thể Listing 7-4 Bạn thêm interface cách kích chuột phải vào thư mục Abstract, chọn Add New Item, chọn Interface Listing 7-4 Nội dung file IProductRepository.cs using System.Collections.Generic; using SportsStore.Domain.Entities; namespace SportsStore.Domain.Abstract { public interface IProductRepository { IEnumerable Products { get; } } } Inerface sử dụng IEnumerable cho phép người gọi nhận trình tự đối tượng Product, mà không cho biết làm nơi mà liệu lưu hay truy xuất Một lớp mà phụ thuộc vào interface IProductRepository có đối tượng Product mà khơng cần phải biết nơi đến làm mà lớp thực thi chuyển Đây chất repository pattern Tơi xem lại interface IProductRepository suốt q trình phát triển để thêm vào tính Tạo Mock Repository Bây định nghĩa abstract interface, tơi thực chế liên tục móc nối đến sở liệu, muốn thêm số thành phần khác ứng dụng trước Để làm điều này, tạo mock implementation interface IProductRepository mà đứng bên tơi quay lại chủ đề lưu trữ liệu Tôi định nghĩa mock implementation ràng buộc vào interface IProductRepository phương thức AddBindings lớp NinjectDependencyResolver project SportsStore.WebUI, minh họa Listing 7-5 Listing 7-5 Thêm Mock IProductRepository Implementation file NinjectDependencyResolver.cs using using using using using using using using System; System.Collections.Generic; System.Linq; System.Web.Mvc; Moq; Ninject; SportsStore.Domain.Abstract; SportsStore.Domain.Entities; namespace SportsStore.WebUI.Infrastructure { public class NinjectDependencyResolver : IDependencyResolver { private IKernel kernel; public NinjectDependencyResolver(IKernel kernelParam) { kernel = kernelParam; AddBindings(); } public object GetService(Type serviceType) { return kernel.TryGet(serviceType); } public IEnumerable GetServices(Type serviceType) { return kernel.GetAll(serviceType); } private void AddBindings() { Mock mock = new Mock (); mock.Setup(m => m.Products).Returns(new List { new Product { Name = "Football", Price = 25 }, new Product { Name = "Surf board", Price = 179 }, new Product { Name = "Running shoes", Price = 95 } }); kernel.Bind().ToConstant(mock.Object); } } } Tôi phải thêm số namespaces vào file cho bổ sung này, q trình mà tơi tạo việc thực thi mock repository sử dụng kỹ thuật Moq giống mà giới thiệu Chương Tôi cần Ninject để trả mock object nhận yêu cầu cho thực thi interface IProductRepository, lý sử dụng phương thức ToConstant để thiết lập phạm vi Ninject, này: kernel.Bind().ToConstant(mock.Object) ; Thay tạo thể đối tượng thực thi lần, Ninject đáp ứng yêu cầu interface IProductRepository với mock object Hiển thị Danh sách Sản phẩm Tơi dành phần lại chương để xây dựng domain model repository, không đụng vào project UI Tôi nghĩ bạn thấy nhàm chán, tơi chuyển hướng bắt đầu sử dụng MVC Framework cách nghiêm túc Tôi thêm vào tính model repository mà tơi cần Trong phần này, tạo controller phương thức hành động để hiển thị thơng tin chi tiết sản phẩm repository Trong thời điểm này, liệu mock repository, xếp sau Tôi thiết lập routing configuration ban đầu để MVC biết cách ánh xạ request cho ứng dụng với controller mà tạo Thêm Controller Click phải vào thư mục Controllers project SportsStore.WebUI chọn Add Controller từ menu sổ Chọn MVC Controller – Empty, click nút Add đặt tên ProductController Click nút Add Visual Studio tạo lớp tên ProductController.cs, mà bạn nên sửa lại để giống Listing 7-6 Listing 7-6 Nội dung ban đầu ProductController.cs using using using using using using using System; System.Collections.Generic; System.Linq; System.Web; System.Web.Mvc; SportsStore.Domain.Abstract; SportsStore.Domain.Entities; namespace SportsStore.WebUI.Controllers { public class ProductController : Controller { private IProductRepository repository; public ProductController(IProductRepository productRepository) { this.repository = productRepository; } } Một phương thức mở rộng sử dụng namespace có chứa Trong file code, điều thực với lệnh using; view Razor, bạn phải thêm mục cấu hình vào file Web.config, thêm lệnh @using để xem Có thể gây nhầm lẫn, hai file Web.config project Razor MVC: chính, nằm thư mục gốc project ứng dụng, view-specific, thư mục Views Sự thay đổi mà muốn file Views/web.config , thể Listing 7-19 Listing 7-19 Thêm Namespace cho phương thức HTML Helper vào file Views/web.config Mỗi namespace mà đề cập đến Razor view cần phải dùng cách rõ ràng, khai báo file web.config áp dụng biểu thức @using Thêm Dữ liệu View Model Tơi chưa hồn tồn sẵn sàng để sử dụng phương thức HTML helper Tôi chưa cung cấp thể lớp view model PagingInfo đến view Tơi làm điều cách sử dụng tính view bag, tơi muốn bọc tất liệu mà gửi từ controller đến view lớp view model Để làm điều này, thêm file tên ProductsListViewModel.cs vào thư mục Models project SportsStore.WebUI Listing 7-20 cho thấy nội dung file Listing 7-20 Nội dung ProductsListViewModel.cs using System.Collections.Generic; using SportsStore.Domain.Entities; namespace SportsStore.WebUI.Models { public class ProductsListViewModel { public IEnumerable Products { get; set; } public PagingInfo PagingInfo { get; set; } } } Tơi cập nhật phương thức List lớp ProductController sử dụng lớp ProductsListViewModel đề cung cấp view với chi tiết sản phẩm hiển thị trang chi tiết phân trang, thể Listing 7-21 Listing 7-21 Cập nhật phương thức List file ProductController.cs using using using using using using using System; System.Collections.Generic; System.Linq; System.Web; System.Web.Mvc; SportsStore.Domain.Abstract; SportsStore.Domain.Entities; using SportsStore.WebUI.Models; namespace SportsStore.WebUI.Controllers { public class ProductController : Controller { private IProductRepository repository; public int PageSize = 4; public ProductController(IProductRepository productRepository) { this.repository = productRepository; } public ViewResult List(int page = 1) { ProductsListViewModel model = new ProductsListViewModel { Products = repository.Products OrderBy(p => p.ProductID) Skip((page - 1) * PageSize) Take(PageSize), PagingInfo = new PagingInfo { CurrentPage = page, ItemsPerPage = PageSize, TotalItems = repository.Products.Count() } }; return View(model); } } } Những thay đổi qua đối tượng ProductsListViewModel model data đến view UNIT TEST: PAGE MODEL VIEW DATA Tôi cần phải đảm bảo controller gửi liệu phân trang xác đến view Dưới unit test mà thêm vào test project để kiểm tra điều này: [TestMethod] public void Can_Send_Pagination_View_Model() { // Arrange Mock mock = new Mock(); mock.Setup(m => m.Products).Returns(new Product[] { new Product {ProductID = 1, Name = "P1"}, new Product {ProductID = 2, Name = "P2"}, new Product {ProductID = 3, Name = "P3"}, new Product {ProductID = 4, Name = "P4"}, new Product {ProductID = 5, Name = "P5"} }); // Arrange ProductController controller = new ProductController(mock.Object); controller.PageSize = 3; // Act ProductsListViewModel result = (ProductsListViewModel)controller.List(2).Model; // Assert PagingInfo pageInfo = result.PagingInfo; Assert.AreEqual(pageInfo.CurrentPage, 2); Assert.AreEqual(pageInfo.ItemsPerPage, 3); Assert.AreEqual(pageInfo.TotalItems, 5); Assert.AreEqual(pageInfo.TotalPages, 2); } Tôi cần phải sửa đổi unit test phân trang trước đó, chứa phương thức Can _Paginate Nó dựa phương thức List trả ViewResult mà thuộc tính Model chuỗi đối tượng Product, tơi gói liệu bên loại view model khác Dưới test sửa đổi: [TestMethod] public void Can_Paginate() { // Arrange Mock mock = new Mock(); mock.Setup(m => m.Products).Returns(new Product[] { new Product {ProductID = 1, Name = "P1"}, new Product {ProductID = 2, Name = "P2"}, new Product {ProductID = 3, Name = "P3"}, new Product {ProductID = 4, Name = "P4"}, new Product {ProductID = 5, Name = "P5"} }); ProductController controller = new ProductController(mock.Object); controller.PageSize = 3; // Act ProductsListViewModel result = (ProductsListViewModel)controller.List(2).Model; // Assert Product[] prodArray = result Products ToArray(); Assert.IsTrue(prodArray.Length == 2); Assert.AreEqual(prodArray[0].Name, "P4"); Assert.AreEqual(prodArray[1].Name, "P5"); } Tôi thường tạo phương thức thiết lập thông thường, đưa mức độ trùng lặp hai phương thức test Tuy nhiên, cung cấp unit test sidebars cá nhân này, giữ tất thứ riêng biệt để bạn nhìn thấy test riêng View chờ trình tự đối tượng Product, tơi cần phải cập nhật file List.cshtml, Listing 7-22, để phân phối với loại view model Listing 7-22 Cập nhật file List.cshtml @model SportsStore.WebUI.Models.ProductsListViewModel @{ ViewBag.Title = "Products"; } @foreach (var p in Model.Products) { @p.Name @p.Description @p.Price.ToString("c") } Tôi thay đổi thị @model để khai báo với Razor làm việc với kiểu liệu khác Tôi cập nhật vòng lặp foreach data source thuộc tính Products model data Hiển thị Page Links (Liên kết trang) Tơi có tất thứ để thêm liên kết trang đến view List Tơi tạo view model có chứa thơng tin phân trang, cập nhật controller để qua thông tin đến view, thay đổi thị @model để phù hợp với loại model view Tất lại gọi phương thức HTML helper từ view, mà bạn thấy Listing 7-23 Listing 7-23 Gọi phương thức HTML Helper file List.cshtml @model SportsStore.WebUI.Models.ProductsListViewModel @{ ViewBag.Title = "Products"; } @foreach (var p in Model.Products) { @p.Name @p.Description @p.Price.ToString("c") } @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new { page = x })) Nếu bạn chạy ứng dụng, bạn thấy liên kết trang mới, minh họa Hình 7-14 Kiểu dáng đơn giản, sửa sau chương Điều quan trọng thời điểm liên kết đưa người dùng từ trang sang trang khác danh mục xem sản phẩm bán Hình 7-14 Hiển thị liên kết điều hướng trang TẠI SAO KHÔNG SỬ DỤNG MỘT GRIDVIEW? Nếu bạn làm việc với ASP.NET trước đó, bạn nghĩ làm nhiều cơng việc để kết khơng ấn tượng Nó đưa cho trang để nhận danh sách trang Nếu sử dụng Web Forms, làm điều tương tự cách sử dụng control GridView ListView ASP.NET Web Forms , cách gắn trực tiếp vào bảng Products Những tơi thực chương có lẽ khơng nhiều, khác với cách kéo control lên giao diện thiết kế Đầu tiên, xây dựng ứng dụng với kiến trúc trì chặt chẽ liên quan đến việc phân tách mối lo ngại Không giống việc đơn giản sử dụng control ListView , không ghép trực tiếp UI với database: phương pháp cho kết nhanh chóng gây khó khăn khổ sở sau Thứ hai, tạo unit test muốn, thứ cho phép xác nhận hành vi ứng dụng cách tự nhiên mà gần khơng thể có với control Web Forms phức tạp Cuối cùng, nhớ nêu lên nhiều chương để tạo sở hạ tầng mà xây dựng ứng dụng Tơi cần phải định nghĩa thực thi repostory lần cho ví dụ, tơi build test tính cách nhanh chóng dễ dàng, chương sau chứng minh Khơng có làm giảm kết tức mà Web Forms mang đến, tơi giải thích Chương 3, gấp rút kèm với giá đắt đau đớn project lớn phức tạp Cải thiện URLs Tơi có liên kết trang hoạt động, họ dùng chuỗi truy vấn để qua thông tin trang đến server, sau: http://localhost/?page=2 Tôi tạo URL hay cách tạo scheme theo mẫu composable URLs Một composable URLs URL có ý nghĩa với người dùng, giống sau: http://localhost/Page2 MVC khiến dễ dàng thay đổi URL scheme ứng dụng sử dụng tính ASP.NET routing Tất tơi cần làm thêm route đến phương thức RegisterRoutes file RouteConfig.cs, mà bạn tìm thấy thư mục App_Start project SportsStore.WebUI Bạn thấy thay đổi mà thực cho tập tin Listing 7-24 Listing 7-24 Thêm Route file RouteConfig.cs using using using using using using System; System.Collections.Generic; System.Linq; System.Web; System.Web.Mvc; System.Web.Routing; namespace SportsStore.WebUI { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: null, url: "Page{page}", defaults: new { Controller = "Product", action = "List" } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional } ); } } } Điều quan trọng bạn thêm route trước Default mà có file Như bạn thấy Chương 15, hệ thống routing xử lý route theo thứ tự chúng liệt kê, cần route để ưu tiên có Đây thay cần thiết để thay đổi URL scheme cho việc phân trang sản phẩm MVC Framework hàm routing tích hợp chặt chẽ, ứng dụng tự động phản ánh thay đổi giống kết tạo phương thức Url.Action (đó tơi sử dụng view List.cshtml để tạo liên kết) Đừng lo lắng routing khơng có ý nghĩa với bạn Tơi giải thích chi tiết Chương 15 16 Nếu bạn chạy ứng dụng điều hướng đến trang, bạn thấy URL scheme hoạt động, minh họa Hình 7-15 Hình 7-15 URL scheme hiển thị trình duyệt Thiết kế nội dung Tơi xây dựng sở hạ tầng lớn ứng dụng bắt đầu đến với nhau, không ý đến xuất Mặc dù sách thiết kế CSS, việc thiết kế ứng dụng SportsStore thảm họa hiển nhiên làm suy yếu sức mạnh kỹ thuật Trong phần này, tơi nêu số điều Tơi thực layout hai cột cổ điển với header, Hình 7-16 Hình 7-16 Mục tiêu thiết kế cho ứng dụng SportsStore Cài đặt Bootstrap Package Tơi sử dụng gói Bootstrap để cung cấp kiểu CSS mà áp dụng cho ứng dụng Để cài đặt gói Bootstrap, chọn Library Package Manager Package Manager Console từ menu Tools Visual Studio mở NuGet command line Nhập vào dòng lệnh sau nhấn Enter: Install-Package -version 3.0.0 bootstrap –projectname SportsStore.WebUI Đây lệnh NuGet mà sử dụng Chương 2, với bổ sung tham số projectname để đảm bảo NuGet thêm file vào project Note Một lần nữa, sử dụng Bootstrap mà không vào chi tiết tính mà package cung cấp Để biết đầy đủ chi tiết Bootstrap thư viện client-side khác mà Microsoft cung cấp để sử dụng với MVC Framework, xem Pro ASP.NET MVC Client tôi, xuất Apress năm 2014 Áp dụng Bootstrap Styles cho Layout Trong chương 5, giải thích Razor layout làm việc làm để áp dụng chúng Khi tạo view List.cshtml cho controller Product, tơi nói bạn check lựa chọn để sử dụng layout, khỏi box mà định layout trống Điều có tác dụng cho việc sử dụng layout quy định file Views/_ViewStart.cshtml, mà Visual Studio tạo tự động với view Bạn xem nội dung file khởi động view Listing 7-25 Listing 7-25 Nội dung file _ViewStart.cshtml @{ Layout = "∼/Views/Shared/_Layout.cshtml"; } Giá trị thuộc tính Layout xác định view sử dụng file Views/Shared/_Layout.cshtml layout, trừ định rõ ràng thay Tôi tạo lại nội dung file _Layout.cshtml trước chương để loại bỏ nội dung template mà Visual Studio thêm, Listing 7-26 bạn thấy tơi trả file để thêm file CSS Bootstrap áp dụng số style CSS mà định nghĩa Listing 7-26 Áp dụng Bootstrap CSS cho file _Layout.cshtml @ViewBag.Title SPORTS STORE Put something useful here later @RenderBody() Tôi dã thêm file bootstrap.css bootstrap- theme.css vào layout cách sử dụng thẻ link áp dụng lớp Bootstrap khác để tạo layout đơn giản Tôi cần thay đổi file List.cshtml , Listing 7-27 Listing 7-27 Áp dụng Bootstrap để tạo kiểu file List.cshtml @model SportsStore.WebUI.Models.ProductsListViewModel @{ ViewBag.Title = "Products"; } @foreach (var p in Model.Products) { @p.Name@p.Price.ToString("c") @p.Description } @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new { page = x })) VẤN ĐỀ VỚI CÁC THẺ STYLING Các thẻ HTML tạo ứng dụng MVC đến từ nhiều nguồn khác (nội dung tĩnh, biểu thức Razor, phương thức HTML helper, v.v), lớp style trở nên khuếch tán suốt project Nếu điều làm cho bạn cảm thấy khó chịu, khơng phải bạn thấy Trộn lẫn style CSS với cấp thẻ thuộc tính khơng phải ý tưởng tuyệt vời ngược lại với ý tưởng tách chức không liên quan mà ngấm vào MVC Bạn cải thiện tình trạng cách gán lớp non-Bootstrap cho thẻ dựa vai trò ứng dụng sau sử dụng thư viện jQuery hay LESS để ánh xạ lớp tùy chỉnh Bootstrap bạn Tôi giữ thứ đơn giản cho ứng dụng chấp nhận nhúng lớp Bootstrap vào khắp ứng dụng, làm phức tạp q trình thay đổi style sau Tôi không làm điều project thực sự, tơi biết ứng dụng ví dụ không vào giai đoạn trì Nếu bạn chạy ứng dụng, bạn thấy cải thiện xuất hiện, dù chút – minh họa Hình 7-17 Hình 7-17 Thiết kế tăng cường ứng dụng SportsStore Tạo Partial View Như thủ thuật cuối cho chương này, cấu trúc lại ứng dụng để đơn giản hóa view List.cshtml Tơi tạo partial view, phần nội dung mà bạn nhúng vào view khác, khơng phải template Partial view chứa file riêng tái sử dụng nhiều view, giúp giảm trùng lặp bạn muốn thực loại liệu vài chỗ ứng dụng bạn Để thêm partial view, click phải vào thư mục /Views/Shared project SportsStore.WebUI chọn Add View từ menu pop-up Đặt View Name ProductSummary, đặt Template Empty, chọn Product từ danh sách sổ xuống Model Class check vào mục Create As A Partial View , Hình 7-18 Hình 7-18 Tạo Partial view Nhấp vào nút Add, Visual Studio tạo file partial view gọi Views/Shared/ProductSummary.cshtml Một partial view tương tự view thơng thường, ngoại trừ việc tạo phần HTML, nội dung HTML đầy đủ Nếu bạn mở view ProductSummary, bạn thấy chứa thị model view, thiết lập cho lớp domain model Product Áp dụng thay đổi thể Listing 7-28 Listing 7-28 Thêm đánh dấu file ProductSummary.cshtml @model SportsStore.Domain.Entities.Product @Model.Name@Model.Price.ToString("c") @Model.Description Bây phải cập nhật Views/Products/List.cshtml đề sử dụng partial view Bạn thấy thay đổi Listing 7-29 Listing 7-29 Sử dụng Partial View file List.cshtml @model SportsStore.WebUI.Models.ProductsListViewModel @{ ViewBag.Title = "Products"; } @foreach (var p in Model.Products) { @Html.Partial("ProductSummary", p) } @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new {page = x})) Tôi đánh dấu trước vòng lặp foreach view List.cshtml di chuyển đến partial view Tơi gọi partial view cách sử dụng phương thức Html.Partial helper Các tham số tên view đối tượng view model Chuyển sang partial view giống thực tốt, khơng thay đổi xuất ứng dụng, Hình 7-19 cho thấy Figure 7-19 Áp dụng partial view Tóm lược Trong chương này, xây dựng hầu hết hạ tầng cốt lõi cho ứng dụng SportsStore Nó khơng có nhiều tính mà bạn trình bày cho khách hàng thời điểm này, đằng sau đó, có bắt đầu domain model với repository sản phẩm hỗ trợ SQL Server Entity Framework Có controller nhất, ProductController, mà tạo danh sách phân trang sản phẩm, thiết lập DI quy định URL scheme rõ ràng thân thiện Nếu chương giống thiết lập nhiều để lợi ích nhỏ, chương cân lại Bây cấu trúc đặt ra, rèn luyện trước thêm tất tính customer-facing: điều hướng theo thể loại, giỏ mua hàng, q trình tốn