Tải bản đầy đủ (.pdf) (44 trang)

7 chuong 07 tủ tài liệu bách khoa

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.1 MB, 44 trang )

CHƯƠNG 7

SportsStore: Một ứng dụng thực tế
Trong chương trước, tôi đã xây dựng các ứng dụng MVC nhanh và đơn giản. Tôi đã mô tả mô hình MVC, những tính
năng C# thiết yếu và các loại công cụ mà các nhà phát triển MVC yêu cầu. Bây giờ là lúc để đưa mọi thứ lại với nhau
và xây dựng một ứng dụng thương mại điện tử đơn giản nhưng thực tế.
Ứng dụng của tôi, gọi là SportsStore, sẽ đi theo phương pháp cổ điển được thực hiện bởi các cửa hàng trực tuyến ở
mọi nơi. Tôi sẽ tạo ra một danh mục sản phẩm trực tuyến mà khách hàng có thể duyệt theo thể loại và theo trang, một
giỏ mua hàng, mà người dùng có thể thêm và loại bỏ các sản phẩm, và một checkout, nơi khách hàng có thể nhập các
chi tiết giao hàng của họ. Tôi cũng sẽ tạo ra một vùng administration bao gồm việc tạo - Create, đọc - Read, cập nhật Update, và xóa - Delete (CRUD) thuận tiện cho việc quản lý các danh mục; và tôi sẽ bảo mật nó để chỉ có các
administrator đã đăng nhập rồi mới có thể chỉnh sửa.
Mục tiêu của tôi trong chương này và những chương sau là để cung cấp cho bạn một cảm giác mà những gì sự
phát triển MVC Framework thực sự đem lại bằng việc tạo ra một ví dụ càng thực tế càng tốt. Tôi muốn tập trung
vào các MVC Framework, tất nhiên, và vì vậy tôi đã đơn giản hóa việc tích hợp với các hệ thống bên ngoài,
chẳng hạn như cơ sở dữ liệu, và bỏ qua hoàn toàn những thứ khác, chẳng hạn như việc xử lý thanh toán.
Bạn có thể thấy tôi đi chậm một chút khi tôi xây dựng lên các cấp của cơ sở hạ tầng mà tôi cần. Chắc chắn, bạn sẽ
có được những chức năng ban đầu được xây dựng một cách nhanh chóng hơn với Web Forms, chỉ bằng cách kéo và
thả các control ràng buộc trực tiếp đến một database.

UNIT TESTING (KIỂM TRA ĐƠN VỊ)
Tôi đã tạo nên một vấn đề lớn về sự dễ dàng của unit testing trong MVC, và niềm tin của tôi rằng unit testing là
một phần quan trọng của quá trình phát triển. Bạn sẽ thấy điều này được chứng minh trong suốt phần này của cuốn
sách vì tôi đã bao hàm các chi tiết của unit test và các kỹ thuật có liên quan đến các tính năng MVC quan trọng.
Tôi biết đây không phải là một ý kiến phổ quát. Nếu bạn không muốn unit test, thì cũng không sao. Đến cuối cùng,
khi tôi phải nói một cái gì đó hoàn toàn về testing, tôi đặt nó trong một sidebar như thế này. Nếu bạn không quan
tâm đến unit test, bạn có thể bỏ qua ngay các phần này, và ứng dụng SportsStore sẽ chỉ hoạt động hơi ổn. Bạn
không cần phải làm bất cứ loại unit test nào để có được những tiện ích công nghệ của ASP.NET MVC, mặc dù tất
nhiên, hỗ trợ testing là một lý do chính cho việc áp dụng MVC Framework.
Hầu hết các tính năng MVC tôi sử dụng cho ứng dụng SportsStore có những chương riêng sau này của nó trong
cuốn sách. Thay vì lặp lại mọi thứ ở đây, tôi chỉ nói với các bạn một chút để tạo cảm nhận cho ứng dụng ví dụ này và
chỉ bạn đến chương khác cho kiến thức chuyên sâu.


Tôi sẽ nêu từng bước cần thiết để xây dựng ứng dụng, do đó bạn có thể thấy làm thế nào các tính năng MVC khớp
với nhau. Bạn nên đặc biệt chú ý khi tôi tạo các view. Bạn sẽ nhận được một số kết quả khác nếu bạn không làm theo
ví dụ một cách chính xác.

Mở đầu
Bạn sẽ phải cài đặt Visual Studio nếu bạn đang có ý định lập trình ứng dụng SportsStore trên máy của bạn khi bạn
đọc qua phần này của cuốn sách. Bạn cũng có thể tải về project SportsStore mà đi kèm với sách này (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 màn hình và danh sách các dòng
lệnh để bạn dễ dàng làm theo nhất có thể.

Tạo Solution và Project trên Visual Studio


Tôi sẽ tạo ra một solution Visual Studio có chứa ba project. Một project sẽ chứa domain model, một cái sẽ là ứng
dụng MVC, và cái thứ ba sẽ chứa các unit test. Để bắt đầu, tôi tạo ra một solution Visual Studio mới được gọi là
SportsStore sử dụng template Blank Solution, mà bạn có thể tìm thấy trong phần Other Project
Types/Visual Studio Solutions Bên trái của hộp thoại New Project, minh họa như Hình 7-1.
Nhấn nút
OK để tạo solution.

Hình 7-1. Tạo một solution Visual Studio mới

Một solution Visual Studio là một phần chứa một hoặc nhiều project. Tôi yêu cầu ba project cho ứng dụng ví dụ của
tôi, mà tôi đã mô tả trong Bảng 7-1. Bạn thêm một project bằng cách click phải vào mục Solution trong Solution
Explorer và 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ữ các đối tượng domain và logic; thiết lập sự bền
vững thông qua một kho lưu trữ được tạo với
Entity Framework.

SportsStore.WebUI

ASP.NET MVC Web Application (chọn Empty khi
được nhắc để chọn project template và đánh dấu
check vào mục MVC)

Giử các controller và view; hoạt động như UI
cho ứng dụng SportsStore.

SportsStore.UnitTests

Unit Test Project

Giữ các unit test cho 2 project kia.


Tôi luôn luôn chọn Empty cho template ASP.NET MVC Web Application. Các lựa chọn khác sẽ thêm
một thiết lập ban đầu cho project bao gồm: các thư viện JavaScript, kiểu CSS, và các lớp C # đề cấu hình các tính năng
của ứng dụng như là bảo mật và routing. Không có cái nào trong đây là xấu - một số thư viện mã nguồn mở mà
Microsoft đã đem ra gần đây trong các project mới là tuyệt vời-nhưng bạn có thể tự thiết lập tất cả các nội dung và cấu
hình, và trong khi làm như vậy,ta tìm hiểu thêm về hoạt động của các MVC Framework.
Khi bạn đã tạo được ba project, Solution Explorer sẽ giống như Hình 7-2. Tôi đã xóa file Class1.cs mà Visual
Studio thêm vào project SportsStore.Domain. Vì tôi sẽ không sử dụng nó.


Hình 7-2. Ba projects được thể hiện trong cửa sổ Solution Explorer

Để debug dễ dàng hơn, chuột phải vào project SportsStore.WebUI và chọn Set as Startup
Project từ menu pop-up (bạn sẽ thấy cái tên chuyển sang in đậm). Điều này nghĩa là khi bạn chọn Start
Debugging hoặc Start without Debugging từ menu Debug , thì project này sẽ khởi động.
Visual Studio sẽ cố điều hướng đến các file view cá nhân nếu bạn đang chỉnh sửa chúng khi bạn khởi động
debugger, vì vậy click phải vào SportsStore.WebUI project trong Solution Explorer và chọn
Properties từ menu pop-up. Click vào Web đề mở các thuộc tính liên quan đến web và chọn Specific
Page. Không cần nhập giá trị vào trong phần Specific Page. Chỉ chọn lựa chọn này là đủ đề ngăn Visual
Studio cố gắng đoán URL mà bạn muốn xem và đảm bảo rằng trình duyệt yêu cầu URL gốc cho ứng dụng khi bạn
khởi động debugger.

Cài dặt các gói công cụ (Tool Packages)
Tôi sẽ sử dụng Ninject và Moq trong chương này. Chọn Tools

Library Package Manager

Package Manager Console trong Visual Studio đề mở dòng lệnh NuGet và 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 vì tôi được lựa chọn gói nào được cài đặt vào trong project nào, và như trong
những chương trước, tôi chỉ rõ phiên bản của các gói để tải xuống và cài đặt.

Thêm References giữa các Project
Tôi cần thiết lập sự phụ thuộc giữa các project và một số các thành phần Microsoft. Click phải vào mỗi project trong

của sổ Solution Explorer, chọn Add Reference, và thêm các reference được thể hiện trong Bảng
7-2 từ


Assemblies

Framework, Assemblies

Extensions hoặc Solution.

Bảng 7-2. Sự phụ thuộc Project được 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 các mối quan hệ một cách chính xác. Nếu bạn không có các thư viện và
project references đúng, bạn sẽ gặp vấn đề khi cố gắng build project.

Thiết lập DI Container
Trong Chương 6, tôi đã cho bạn thấy làm thế nào sử dụng Ninject để tạo một sự phân giải phụ thuộc tùy chỉnh mà
MVC Framework sẽ sử dụng để khởi tạo đối tượng thông qua ứng dụng. Tôi sẽ lặp lại tiến trình đó, bắt đầu với việc
thêm một thư mục Infrastructure trong SportsStore.WebUI project và thêm một file class gọi là
NinjectDependencyResolver.cs trong đó. Bạn có thể thấy nội dụng của file mới trong Listing 7-1.
Listing 7-1. Nội dung của 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<object> GetServices(Type
serviceType) { return kernel.GetAll(serviceType);
}
private void AddBindings()
{ // put bindings here
}
}
}


Như bạn có thể nhớ lại từ Chương 6, bước tiếp theo là tạo ra một cầu nối giữa lớp

NinjectDependencyResolver và MVC support cho việc chèn phụ thuộc trong file
App_Start/NinjectWebCommon.cs, mà một trong các gói NuGet Ninject đã thêm vào project, như trong
Listing 7-2.
Listing 7-2. Tích hợp Ninject trong 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 sẽ thấy một trang bị lỗi như Hình 7-3. Điều này là
bởi vì bạn đã request một URL có liên quan với một controller không tồn tại.


Hình 7-3. Trang bị lỗi

Khởi động Domain Model
Tất cả các project MVC Framework bắt đầu với domain model bởi vì tất cả mọi thứ trong một ứng dụng MVC
Framework đều xoay quanh nó. Vì đây là một ứng dụng thương mại điện tử, các thực thể domain rõ ràng nhất mà tôi
cần là một sản phẩm. Tạo một thư mục mới có tên gọi Entities bên trong project SportsStore.Domain
và sau đó tạo một lớp C # mới tên là Product.cs ở bên trong nó. Bạn có thể nhìn cấu trúc này trong Hình 7-4.


Hình 7-4. tạo lớp Product

Bạn đã quen thuộc với các định nghĩa trong lớp Product, vì vậy tôi sẽ sử dụng một trong những cái mà bạn
đã thấy trong các chương trước. Chỉnh sửa lớp Product.cs để nó giống như Listing 7-3.
Listing 7-3. Nội dung của 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 đang làm theo các kỹ thuật định nghĩa domain model của tôi trong một project Visual Studio riêng biệt, có nghĩa
là các lớp phải được đánh dấu là public. Bạn không cần phải tuân theo quy tắc này, nhưng tôi thấy rằng nó giúp
giữ cho các model riêng biệt với các controller, điều đó là hữu ích trong các project lớn và phức tạp.

Tạo một Abstract Repository
Tôi cần một số cách để nhận các thực thể Product từ một database. Như tôi đã giải thích trong Chương 3, model
bao gồm việc luận lý học liên tục cho việc lưu trữ và truy xuất dữ liệu từ các kho dữ liệu liên tục, ngay cả bên trong
model. Tôi muốn giữ một mức độ tách biệt giữa các thực thể data model và nơi lưu trữ và truy xuất lôgic , mà tôi đạt
được bằng cách sử dụng repository pattern. Tôi sẽ không lo lắng về việc làm thế nào mà tôi sẽ thực thi dữ liệu liên
tục trong chốc lát, nhưng tôi sẽ bắt đầu quá trình xác định một interface cho nó.
Tạo một thư mục cấp cao mới bên trong project SportsStore.Domain tên là Abstract và bên trong

thư mục mới, tạo một file interface mới tên là IProductsRepository.cs, nội dung của nó thể hiện ở
Listing 7-4 . Bạn có thể thêm một interface mới bằng cách kích chuột phải vào thư mục Abstract, chọn Add
New Item, và chọn Interface.
Listing 7-4. Nội dung của file IProductRepository.cs

using System.Collections.Generic;
using SportsStore.Domain.Entities;
namespace SportsStore.Domain.Abstract {
public interface IProductRepository
{
IEnumerable<Product> Products { get; }
}
}
Inerface này sử dụng IEnumerable<T> cho phép người gọi nhận được một trình tự của các đối tượng
Product, mà không cho biết làm thế nào và nơi nào mà dữ liệu được lưu hay truy xuất. Một lớp mà phụ thuộc vào
interface IProductRepository có thể có được các đối tượng Product mà không cần phải biết gì về nơi nó

đến hoặc làm thế nào mà các lớp thực thi sẽ chuyển nó đi. Đây là bản chất của repository pattern. Tôi sẽ xem lại
interface IProductRepository trong suốt quá trình phát triển để thêm vào các tính năng.


Tạo ra một Mock Repository
Bây giờ tôi đã định nghĩa một abstract interface, tôi có thể thực hiện các cơ chế liên tục và móc nối nó đến một cơ sở
dữ liệu, nhưng tôi muốn thêm một số thành phần khác của ứng dụng trước. Để làm điều này, tôi sẽ tạo ra một mock
implementation của interface IProductRepository mà sẽ đứng bên trong đó cho đến khi tôi quay lại chủ đề
về lưu trữ dữ liệu.
Tôi định nghĩa mock implementation và ràng buộc nó vào interface IProductRepository trong phương thức

AddBindings của lớp NinjectDependencyResolver trong project SportsStore.WebUI, như
minh họa trong Listing 7-5.
Listing 7-5. Thêm Mock IProductRepository Implementation trong 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<object> GetServices(Type
serviceType) { return kernel.GetAll(serviceType);
}
private void AddBindings() {
Mock<IProductRepository> mock = new Mock<IProductRepository>
();
mock.Setup(m => m.Products).Returns(new
List<Product> { new Product { Name = "Football",
Price = 25 },
new Product { Name = "Surf board", Price = 179
}, new Product { Name = "Running shoes", Price
= 95 }
});
kernel.Bind<IProductRepository>().ToConstant(mock.Object);



}
}
}
Tôi đã phải thêm một số namespaces vào file cho sự bổ sung này, quá trình mà tôi đã tạo ra việc thực thi mock
repository sử dụng các kỹ thuật Moq giống nhau mà tôi đã giới thiệu trong Chương 6. Tôi cần Ninject để trả về cùng
mock object bất cứ khi nào nó nhận được một yêu cầu cho một thực thi của interface IProductRepository,
đó là lý do tại sao tôi sử dụng phương thức ToConstant để thiết lập phạm vi Ninject, như thế này:

...
kernel.Bind<IProductRepository>().ToConstant(mock.Object) ;
...
Thay vì tạo ra một thể hiện mới của các đối tượng thực thi mỗi một lần, Ninject sẽ luôn đáp ứng yêu cầu của
interface IProductRepository với cùng mock object.

Hiển thị một Danh sách Sản phẩm
Tôi có thể dành phần còn lại của chương này để xây dựng domain model và repository, và không đụng vào các project
UI nào cả. Tôi nghĩ rằng bạn sẽ thấy nhàm chán, vì vậy tôi sẽ chuyển các hướng đi và bắt đầu sử dụng MVC
Framework một cách nghiêm túc. Tôi sẽ thêm vào các tính năng model và repository mà tôi cần.
Trong phần này, tôi sẽ tạo ra một controller và một phương thức hành động để có thể hiển thị thông tin chi tiết của
sản phẩm trong repository. Trong thời điểm này, đây chỉ là những dữ liệu trong mock repository, nhưng tôi sẽ sắp xếp
sau. Tôi cũng sẽ thiết lập một routing configuration ban đầu để MVC biết cách ánh xạ các request cho ứng dụng với
controller mà tôi tạo.

Thêm một Controller
Click phải vào thư mục Controllers trong project SportsStore.WebUI và chọn Add
Controller từ menu sổ ra. Chọn MVC 5 Controller – Empty, click nút Add và đặt tên
ProductController. Click nút Add và Visual Studio sẽ tạo một lớp mới tên là
ProductController.cs, mà bạn nên sửa lại để giống Listing 7-6.
Listing 7-6. Nội dung ban đầu của 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;
}
}


}
Ngoài việc xóa bỏ phương thức Index, tôi đã thêm một constructor để khai báo một sự phụ thuộc trên interface
IProductRepository, nó sẽ dẫn Ninject chèn sự phụ thuộc cho repository sản phẩm khi nó khởi tạo lớp
controller. Tôi cũng thêm vào namespaces SportsStore.Domain , vì vậy tôi thể tham chiếu các lớp model

và repository mà không cần phải định danh cho nó. Tiếp theo, tôi đã thêm một phương thức hành động, tên là
List, mà sẽ trả lại một view thể hiện danh sách đầy đủ của sản phẩm, như được hiển thị trong Listing 7-7.
Listing 7-7. Thêm một phương thức hành động trong ProductController.cs

using System;
using
System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
namespace SportsStore.WebUI.Controllers {
public class ProductController : Controller
{ private IProductRepository
repository;
public ProductController(IProductRepository
productRepository) { this.repository = productRepository;
}
public ViewResult List() {
return View(repository.Products);
}
}
}
Gọi phương thức View giống như thế này (không chỉ định một tên view) khiến cho framework tạo ra view mặc
định cho phương thức hành động. Cho phép một List của đối tượng Product đến phương thức View, cung cấp
framework với dữ liệu ở cùng đối tượng Model trong một strongly-typed view.

Thêm Layout, View Start File và View
Bây giờ tôi cần phải thêm view mặc định cho phương thức List. Nhấp chuột phải vào phương thức List trong lớp

HomeController và chọn Add View từ menu pop-up. Đặt View Name là List, đặt Template là
Empty, và chọn Product cho Model Class, như thể hiện trong Hình 7-5. Đảm bảo rằng Use A Layout
Page được đánh dấu check và nhấn vào nút Add để tạo ra view.


Hình 7-5. Thêm Views/Product/List.cshtml view

Khi bạn nhấn vào nút Add, Visual Studio sẽ tạo ra file List.cshtml, nhưng nó cũng sẽ tạo ra một file
_ViewStart.cshtml và một file Shared/_Layout.cshtml. Đây là một tính năng hữu ích, phù hợp
với cách tiếp cận của Microsoft để mặc định nội dung, file _Layout.cshtml chứa nội dung mẫu mà tôi không
muốn và không cần. Chỉnh sửa layout sao cho nó phù hợp với nội dung hiển thị trong Listing 7-8.
Listing 7-8. Sửa tập tin _Layout.cshtml

html> <html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initialscale=1.0"> <title>@ViewBag.Title</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>

Trả về View Data
Mặc dù tôi đặt model type của view là lớp Product, tôi thực sự muốn làm việc với một
IEnumerable<Product>, đó là những gì Product controller thu được từ các repository và chuyển sang
view. Trong Listing 7-9, bạn có thể thấy rằng tôi đã chỉnh sửa @model expression và thêm một số cú pháp

HTML và Razor để hiển thị chi tiết của sản phẩm.
Listing 7-9. Sửa tập tin List.cshtml

@using
SportsStore.Domain.Entities
@model IEnumerable<Product>
@{
ViewBag.Title = "Products";
}
@foreach (var p in Model)
{ <div>

@p.Name


@p.Description

@p.Price.ToString("c")


</div>
}
Tôi cũng đã thay đổi tiêu đề trang. Chú ý rằng tôi không cần sử dụng biểu thức Razor @: để hiển thị view data.
Điều này là vì mỗi dòng nội dung trong phần thân code là một chỉ thị Razor hoặc bắt đầu với một thẻ HTML.


Mẹo: Tôi chuyển đổi thuộc tính Price cho một chuỗi bằng cách sử dụng phương thức ToString("c"),
điều này trả về các giá trị số như là tiền tệ, phù hợp với thiết lập nền văn hóa đang có trên server của bạn. Ví dụ, nếu
máy chủ được thiết lập là en-US, thì (1002.3).ToString("c")sẽ trả về giá trị $1,002.30, nhưng nếu
máy chủ được đặt là en-GB, thì phương thức đó sẽ trả về giá trị £1,002.30. Bạn có thể thay đổi các thiết lập nền
văn hóa cho server của bạn bằng cách thêm một phần ở mục <system.web> trong file Web.config như thế
này: <globalization culture="en-GB" uiCulture="en-GB" />.

Thiết lập Default Route
Tôi cần phải khai báo cho MVC Framework là nó nên gửi các request đến root URL của ứng dụng
(http://mysite/) cho phương thức List trong lớp ProductController. Tôi làm điều này bằng cách

chỉnh sửa các dòng lệnh trong phương thức RegisterRoutes trong file
App_Start/RouteConfig.cs, như thể hiện trong Listing 7-10.
Listing 7-10. Thêm Default Route trong 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: "Default",

url: "{controller}/{action}/{id}",
defaults: new { controller = "Product", action =
"List", id = UrlParameter.Optional }

);
}
}
}
Bạn có thể thấy những thay đổi được in đậm. Thay Home thành Product và Index thành List, như được
hiển thị trong listing. Tôi bao trùm các chi tiết tính năng routing của ASP.NET trong Chapters 15 và 16. Còn bây giờ,
cũng đủ để hiểu rằng sự thay đổi này gửi các yêu cầu cho URL mặc định đến phương thức List trong controller
Product.
Mẹo Chú ý rằng tôi đã thiết lập các giá trị của controller trong Listing 7-10 là Product chứ không phải
ProductController, đó là tên của lớp. Đây là một phần của naming scheme ASP.NET MVC, trong đó các
lớp controller luôn luôn kết thúc bằng Controller, nhưng bạn bỏ qua phần tên này khi đề cập đến các class.

Chạy ứng dụng
Tôi có tất cả những điều cơ bản tại đây. Tôi có một controller với một phương thức hành động mà MVC Framework sẽ
gọi khi default URL được yêu cầu. Phương thức này dựa trên một mock implementation của repository interface, nó tạo
ra một số dữ liệu test đơn giản. Controller chuyển dữ liệu test đến view mà tôi đã liên kết với phương thức, và lớp view


hiển thị một danh sách đơn giản chi tiết cho từng sản phẩm. Bạn có thể xem kết quả bằng cách chạy thử ứng dụng, như
trong Hình 7-6. Nếu bạn không nhận được kết quả như trong hình, kiểm tra xem bạn đã điều hướng đến default URL
chưa và không trỏ đến action khác.


Hình 7-6. Xem các chức năng của ứng dụng cơ bản

Đây là mô hình điển hình của sự phát triển ASP.NET MVC Framework. Đầu tư thời gian ban đầu để thiết lập tất cả
mọi thứ cần thiết, và rồi các tính năng cơ bản của ứng dụng khớp nhau một cách nhanh chóng.

DEBUGGING DỄ HƠN
Khi bạn chạy project từ menu Debug, Visual Studio sẽ tạo ra một cửa sổ trình duyệt mới để hiển thị

ứng dụng, điều này có thể mất vài giây. Có một số thủ thuật mà bạn có thể dùng để tăng tốc quá trình.
Nếu bạn đang chỉnh sửa tập tin view mà không phải các class, thì bạn có thể thực hiện chỉnh sửa trong Visual
Studio trong khi debugger vẫn đang chạy. Tải lại cửa sổ trình duyệt khi bạn muốn thấy hiệu ứng của việc chỉnh
sửa của bạn. ASP.NET sẽ biên dịch lại các view của bạn bên trong các lớp và hiển thị các thay đổi ngay lập tức.
Visual Studio sẽ không cho bạn chỉnh sửa các file class khi debugger đang chạy hoặc tạo một số thay đổi với
project trong Solution Explorer, vì vậy kĩ thuật này hữu dụng nhất khi bạn đang tinh chỉnh sự phù hợp và sự
hoàn thiện của HTML mà ứng dụng của bạn tạo ra.
Visual Studio 2013 bao gồm một tính năng mới được gọi là browser link , cho phép bạn mở nhiều cửa sổ trình
duyệt và tải lại nó từ thanh menu Visual Studio. Tôi giới thiệu tính năng này trong Chương 14.
Như một thay thế cuối cùng, bạn có thể giữ cho ứng dụng của bạn mở trong một cửa sổ trình duyệt độc lập. Để
làm được điều này (giả sử bạn đã khởi chạy debugger ít nhất một lần rồi), kích chuột phải vào biểu tượng IIS
Express trong khay hệ thống và chọn URL cho ứng dụng của bạn từ menu pop-up. Sau khi bạn đã thực hiện các
thay đổi, biên dịch solution trong Visual Studio bằng cách nhấn F6 hoặc chọn Build
Build
Solution, và sau đó chuyển sang cửa sổ trình duyệt của bạn và tải lại trang web.

Chuẩn bị một Cơ sở dữ liệu
Tôi đã có thể hiển thị các view đơn giản có chứa thông tin chi tiết của sản phẩm, nhưng tôi đang hiển thị dữ liệu test
mà mock IproductRepository trả về. Trước khi tôi có thể thực thi một repository thực sự, tôi cần phải thiết
lập một cơ sở dữ liệu và đưa vào đó một số dữ liệu.


Tôi sẽ sử dụng SQL Server như cơ sở dữ liệu, và tôi sẽ truy cập vào cơ sở dữ liệu bằng cách sử dụng Entity
Framework (EF), đó là framework Microsoft.NET ORM. Một framework ORM thể hiện các bảng, cột, và các hàng
của một cơ sở dữ liệu quan hệ thông qua các đối tượng C # bình thường. Tôi đã đề cập trong Chương 6 là LINQ có
thể làm việc với các nguồn dữ liệu khác nhau, và một trong số này là các Entity Framework. Bạn sẽ thấy cách này
làm đơn giản hóa mọi thứ trong một thời gian ngắn.
Chú ý Đây là vùng mà bạn có thể chọn từ một loạt các công cụ và công nghệ. Không chỉ có các cơ sở dữ liệu quan
hệ khác nhau có sẵn, mà bạn cũng có thể làm việc với đối tượng repository, các nơi lưu trữ tài liệu, và một số sự thay
thế bí mật. Có những framework .NET ORM khác cũng khá tốt, mỗi cái trong số đó có một cách tiếp cận hơi khác

nhau: Các biến có thể cung cấp cho bạn một sự phù hợp tốt hơn cho các project của bạn.
Tôi đang sử dụng Entity Framework vì một số lý do: nó đơn giản và dễ dàng để gọi nó lên để làm việc; sự tích hợp
với LINQ là sự đánh giá đầu tiên ( tôi thích sử dụng LINQ) và nó rất tốt. Các bản phân phối trước đó có một chút hitand-miss (lúc được lúc không), nhưng phiên bản hiện tại thì sang trọng và nhiều tính năng.

Tạo Cơ sở dữ liệu
Một tính năng rất hay của Visual Studio và SQL Server là tính năng LocalDB, nó là một sự thực thi administration-free
của các tính năng SQL Server thiết yếu được thiết kế đặc biệt cho các nhà phát triển. Sử dụng tính năng này, tôi có thể
bỏ qua quá trình thiết lập một cơ sở dữ liệu khi tôi xây dựng project của tôi và sau đó triển khai một thể hiện SQL
Server đầy đủ. Hầu hết ứng dụng MVC được triển khai để chứa các môi trường được chạy bởi các quản trị viên chuyên
nghiệp. Do đó, tính năng LocalDB có nghĩa là việc cấu hình cơ sở dữ liệu có thể trong tầm tay của các DBA và các
developer, đạt được với việc lập trình. Các tính năng LocalDB được cài tự động với Visual Studio Express 2013 for
Web, nhưng bạn có thể tải về trực tiếp từ www.microsoft.com/sqlserver nếu bạn thích.
Bước đầu tiên là tạo kết nối cơ sở dữ liệu trong Visual Studio. Mở cửa sổ Server Explorer từ menu
View và click nút Connect to Database (nó trông giống như một ổ cắm điện với một dấu cộng
màu xanh).
Bạn sẽ thấy hộp thoại Choose Data Source. Chọn Microsoft SQL Server, như trong Hình 7-7,
và click nút Continue. (Visual Studio ghi nhớ lựa chọn của bạn, vì vậy bạn sẽ không thấy cửa sổ này nếu bạn đã
từng tạo một kết nối trong project khác).

Hình 7-7. Chọn Nguồn Cơ sở dữ liệu

Tiếp theo, bạn sẽ thấy hộp thoại Add Connection. Đặt server name là (localdb)\v11.0. Đây là một
tên đặc biệt để chỉ ra rằng bạn muốn sử dụng tính năng LocalDB. Đánh dấu vào lựa chọn Use Windows
Authentication và đặt tên cơ sở dữ liệu là SportsStore, như trong Hình 7-8.


Hình 7-8. Thiết lập cơ sở dữ liệu SportsStore

Mẹo Nếu bạn không thấy hộp thoại Choose Data Source, bạn có thể click nút Change ở phía trên bên
phải của hộp thoại Add Connection.

Click nút OK và Visual Studio sẽ nhắc bạn tạo cơ sở dữ liệu mới: click Yes để đi tiếp. Một mục sẽ xuất hiện trong
phần Data Connections của cửa sổ Server Explorer, mà bạn có thể sổ ra để nhìn các khía cạnh khác nhau của
cơ sở dữ liệu, như thể hiện trong Hình 7-9. Bạn sẽ thấy một cái gì đó tương tự, nhưng tên của kết nối cơ sở dữ liệu sẽ
khác nhau vì nó bao gồm tên máy tính nội bộ (tên máy của tôi là tiny).


Hình 7-9. Cơ sở dữ liệu LocalDB được thể hiện trong cửa sổ Server Explorer

Định nghĩa Sơ đồ Cơ sở dữ liệu (Database Schema)
Như tôi đã giải thích ở đầu chương, sự tập trung của tôi với ứng dụng SportsStore là tập trung vào quá trình phát triển
MVC Framework, có nghĩa là giữ cho các thành phần khác mà ứng dụng dựa vào càng đơn giản càng tốt. Tôi không
muốn quan tâm vào chủ đề thiết kế cơ sở dữ liệu và các chi tiết chuyên sâu về Entity Framework, vượt ra ngoài những
gì tôi cần phải chứng tỏ làm thế nào để dữ liệu vào và ra khỏi một ứng dụng. Đây là những chủ đề riêng của nó và nó
không phải là một phần của ASP.NET hoặc MVC Framework.
Với điều này trong suy nghĩ, tôi sẽ sử dụng một cơ sở dữ liệu mà chỉ chứa một bảng. Đây không phải là cách các
trang web thương mại điện tử thực sự cấu trúc dữ liệu của họ, tất nhiên, nhưng những bài học quan trọng trong phần
này là về các mô hình repository và làm thế nào tôi sử dụng nó để lưu trữ và truy xuất dữ liệu, không phải là cấu trúc
của cơ sở dữ liệu.
Để tạo bảng cơ sở dữ liệu, click phải vào mục Tables cho cơ sở dữ liệu SportsStore mới trong cửa sổ Server
Explorer và chọn Add New Table, như thể hiện trong Hình 7-10.

Hình 7-10. Thêm một bảng mới


Visual Studio sẽ hiển thị một cửa sổ thiết kế cho việc tạo một bảng mới. Bạn có thể tạo một bảng cơ sở dữ liệu mới
bằng cách sử dụng giao diện của phần thiết kế, nhưng tôi sẽ sử dụng phần T-SQL bởi vì cách này ngắn gọn và chính
xác hơn cho việc mô tả các đặc điểm của bảng mà tôi muốn. Nhập câu lệnh SQL được hiển thị trong Listing 7-11 và
nhấp vào nút Update ở góc trên bên trái của cửa sổ thiết kế bảng.
Listing 7-11. Câu lệnh SQL để tạo bảng trong cơ sở dữ liệu SportsStore


CREATE TABLE Products
(
[ProductID] INT NOT NULL PRIMARY KEY
IDENTITY, [Name] NVARCHAR(100) NOT NULL,
[Description] NVARCHAR(500) NOT
NULL, [Category] NVARCHAR(50) NOT
NULL, [Price] DECIMAL(16, 2) NOT
NULL
)
Câu lệnh này tạo một bảng tên là Products, nó có những cột với các thuộc tính khác nhau mà tôi đã định nghĩa
trong lớp Product trước đó trong chương này.
Mẹo Đặt thuộc tính IDENTITY cho cột ProductID có nghĩa là SQL Server sẽ tạo ra một giá trị khóa chính
duy nhất khi tôi thêm dữ liệu vào bảng. Khi sử dụng một cơ sở dữ liệu trong một ứng dụng Web, có thể khó khăn để
tạo ra khóa chính duy nhất vì các request từ người dùng đến một cách đồng thời. Với việc dùng tính năng này, tôi có
thể lưu trữ các dòng mới và dựa vào SQL Server để sắp ra giá trị duy nhất.
Khi bạn click nút Update, Visual Studio sẽ thể hiện tóm tắt kết quả của câu lệnh, như thể hiện trong Hình 7-11.

Hình 7-11. Tóm tắt kết quả của câu lệnh SQL

Click nút Update Database để thực thi SQL và tạo bảng Products trong cơ sở dữ liệu. Bạn sẽ có thể
thấy kết quả của việc cập nhật nếu bạn nhấp vào nút Refresh trong cửa sổ Server Explorer. Phần Tables thể
hiện bảng Product mới và các chi tiết của mỗi dòng.
Mẹo Sau khi bạn đã cập nhật cơ sở dữ liệu, bạn có thể đóng cửa sổ dbo.Products. Visual Studio sẽ cho bạn
cơ hội để lưu các tập lệnh SQL được sử dụng để tạo ra cơ sở dữ liệu. Bạn không cần phải lưu các tập lệnh trong chương
này, nhưng nó sẽ hữu ích trong các project thực tế nếu bạn cần phải cấu hình nhiều cơ sở dữ liệu.


Thêm Dữ liệu cho Cơ sở dữ liệu
Tôi sẽ thêm dữ liệu vào cơ sở dữ liệu để có một cái gì đó để làm việc cho đến khi tôi thêm các tính năng quản trị
danh mục trong Chương 11.

Trong cửa sổ Server Explorer, mở rộng mục Tables của cơ sở dữ liệu SportsStore, kích chuột
phải vào bảng Products, và chọn Show Table Data. Nhập các dữ liệu được hiển thị trong Hình 7-12. Bạn
có thể di chuyển đến hàng khác bằng cách sử dụng phím Tab. Ở cuối mỗi hàng, nhấn tab sẽ di chuyển đến dòng kế
tiếp và cập nhật dữ liệu trong cơ sở dữ liệu.

Hình 7-12. Thêm dữ liệu vào bảng Products

Chú ý Bạn phải rời khỏi cột ProductID trống. Nó là một cột định danh, do đó SQL Server sẽ tạo ra một giá trị duy
nhất khi bạn tab đến hàng tiếp theo.
Tôi đã liệt kê các chi tiết sản phẩm trong Bảng 7-3 trong trường hợp bạn không thể tạo ra từ số liệu. Nó cũng
không quan trọng nếu bạn không nhập các chi tiết đúng như tôi đã làm, mặc dù bạn sẽ thấy kết quả khác nhau từ
những cái mà tôi thể hiện khi bạn làm việc thông qua quá trình tạo ra các phần còn lại của ứng dụng SportsStore.
Bảng 7-3. Dữ liệu cho bảng Products


Tạo Entity Framework Context
Các phiên bản gần đây của Entity Framework có một tính năng khá hay là code-first. Ý tưởng là tôi có thể định nghĩa
các lớp trong model của tôi và sau đó tạo ra một cơ sở dữ liệu từ những lớp đó.
Điều này là tốt cho các project phát triển green-field, nhưng những cái này rất ít. Thay vào đó, tôi sẽ cho bạn thấy
một biến thể của code-first, nơi tôi kết hợp các lớp model với một cơ sở dữ liệu hiện có. Chọn Tools
Library Package Manager
Package Manager Console trong Visual Studio để mở
dòng lệnh NuGet và nhập vào lệnh sau đây:

Install-Package EntityFramework -projectname SportsStore.Domain
Install-Package EntityFramework -projectname SportsStore.WebUI
Mẹo Bạn có thể thấy các lỗi trong Package Manager Console khai báo với bạn rằng binding redirects
(ràng buộc chuyển hướng) không thể được tạo ra. Bạn có thể yên tâm bỏ qua những cảnh báo này.
Lệnh này thêm các gói Entity Framework cho solution. Tôi cần phải cài đặt các gói phần mềm tương tự trong project
Domain và WebUI, vì vậy mà tôi tạo ra các lớp mà nó sẽ truy cập vào cơ sở dữ liệu trong project Domain và

WebUI.
Bước tiếp theo là tạo ra một lớp context mà sẽ kết hợp model với cơ sở dữ liệu. Tạo một thư mục mới trong project
SportsStore.Domain gọi là Concrete và thêm một class mới gọi là EFDbContext.cs trong thư
mục đó . Chỉnh sửa nội dung của file class cho phù hợp với Listing 7-12.
Listing 7-12. Nội dung của EFDbContext.cs

using SportsStore.Domain.Entities;
using System.Data.Entity;
namespace SportsStore.Domain.Concrete {
public class EFDbContext : DbContext {
public DbSet<Product> Products { get; set; }
}
}
Để tận dụng lợi thế của các tính năng code-first, tôi cần phải tạo ra một lớp có xuất phát từ
System.Data.Entity.DbContext. Lớp này sau đó sẽ tự động xác định một thuộc tính cho mỗi bảng
trong cơ sở dữ liệu mà tôi muốn làm việc.


Tên của thuộc tính sẽ quy định bảng, và tham số kiểu của kết quả DbSet quy định các kiểu model mà Entity
Framework sẽ sử dụng để đại diện cho các hàng trong bảng đó. Trong trường hợp này, tên thuộc tính là Products và
các tham số kiểu là Product, nghĩa là Entity Framework sẽ sử dụng kiểu model Product để đại diện cho các hàng
trong bảng Products.
Tiếp theo, tôi cần nói Entity Framework kết nối với cơ sở dữ liệu như thế nào, bằng cách thêm vào một chuỗi kết nối
cơ sở dữ liệu vào file Web.config trong project SportsStore.WebUI với tên giống như các lớp context,
như thể hiện trong Listing 7-13.
Listing 7-13. Thêm một kết nối cơ sở dữ liệu trong tập tin Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>

providerName="System.Data.SqlClient"/>
</connectionStrings>
<appSettings>
/> />
<add key="ClientValidationEnabled" value="true" />
/>
</appSettings>
<system.web>
/> <httpRuntime targetFramework="4.5.1" />
</system.web>
</configuration>
Mẹo Thông báo rằng tôi đã chuyển project ở đây. Tôi định nghĩa model và repository logic trong project

SportsStore.Domain, mặc dù thông tin kết nối cơ sở dữ liệu được đặt trong file Web.config trong project
SportsStore.WebUI .
Cảnh báo Tôi đã phải chia giá trị thuộc tính connectionString trên nhiều dòng để phù hợp với trang này,
nhưng điều quan trọng là phải đặt tất cả mọi thứ trên một dòng trong file Web.config.
Sẽ có thẻ add khác trong phần connectionsStrings của file Web.config. Visual Studio tạo ra thẻ
này theo mặc định và bạn có thể bỏ qua nó hoặc như tôi làm, xóa nó từ tập tin Web.config.

Tạo Product Repository
Tất cả những gì còn lại là thêm một lớp vào thư mục Concrete của project


SportsStore.Domain gọi là EFProductRepository.cs. Chỉnh sửa lớp của bạn để nó
giống với Listing 7-14.
Listing 7-14. Nội dung của EFProductRepostory.cs


using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using System.Collections.Generic;
namespace SportsStore.Domain.Concrete {
public class EFProductRepository : IProductRepository {
private EFDbContext context = new EFDbContext();
public IEnumerable<Product> Products
{ get { return context.Products;
}
}
}
}
Đây là lớp repository. Nó thực thi interface IProductRepository và sử dụng một thể hiện của
EFDbContext để lấy dữ liệu từ cơ sở dữ liệu bằng cách sử dụng Entity Framework. Bạn sẽ thấy cách tôi làm
việc với Entity Framework (và thấy nó đơn giản thế nào) khi tôi thêm các tính năng cho repository.
Để sử dụng lớp repository mới, tôi cần phải chỉnh sửa các ràng buộc Ninject và thay thế các mock repository với một
ràng buộc cho real repository. Chỉnh sửa lớp NinjectDependencyResolver.cs trong project
SportsStore.WebUI để phương thức AddBindings trông giống như Listing 7-15.
Listing 7-15. Thêm Ràng buộc Real Repository trong NinjectDependencyResolver.cs

using
using
using
using

using
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Web.Mvc;
Moq;
Ninject;
SportsStore.Domain.Abstract;
SportsStore.Domain.Concrete;
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<object> GetServices(Type serviceType)
{ return kernel.GetAll(serviceType);
}



private void AddBindings() {
kernel.Bind<IProductRepository>().To<EFProductRepository>(
);
}
}
}
Các ràng buộc mới được in đậm. Nó khai báo với Ninject tạo các thể hiện của lớp EFProductRepository
cho dịch vụ để yêu cầu cho interface IProductRepository. Tất cả những gì còn lại bây giờ là chạy ứng dụng
một lần nữa. Hình 7-13 cho thấy kết quả, trong đó thể hiện ứng dụng đang nhận được dữ liệu sản phẩm của nó từ cơ sở
dữ liệu, chứ không phải là mock repository.

Figure 7-13. Kết quả của việc thực thi real repository

Mẹo Nếu bạn nhận được System.ArgumentException khi bạn khởi động project, thì bạn đã tách các
chi tiết của kết nối cơ sở dữ liệu thành hai dòng trong file Web.config. Xem phần trước để biết chi tiết.
Cách tiếp cận này để cho Entity Framework thể hiện một cơ sở dữ liệu SQL Server, như các đối tượng model đơn
giản và dễ dàng làm việc với nó, và nó cho phép tôi tiếp tục tập trung vào MVC Framework. Tất nhiên, tôi đang bỏ qua
rất nhiều chi tiết trong cách Entity Framework hoạt động và số lượng lớn các tùy chọn cấu hình có sẵn. Tôi thích Entity
Framework rất nhiều và tôi khuyên bạn nên dành chút thời gian để tìm hiểu chi tiết. Một chỗ tốt để bắt đầu là trang web
Microsoft cho Entity Framework: />
Thêm Pagination (Phân trang)
Bạn có thể thấy trong Hình 7-13 rằng view List.cshtml hiển thị tất cả các sản phẩm trong cơ sở dữ liệu trên một
trang duy nhất. Trong phần này, tôi sẽ hỗ trợ thêm cho việc đánh số trang để view hiển thị chỉ một số sản phẩm trên
một trang, và người dùng có thể di chuyển từ trang này sang trang khác để xem danh mục tổng thể. Để làm điều này,
tôi sẽ để thêm một tham số cho phương thức List trong controller Product, như được hiển thị trong Listing 7-16.
Listing 7-16. Thêm hỗ trợ phân trang cho phương thức List trong 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;

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)
{ return
View(repository.Products
.OrderBy(p => p.ProductID)
.Skip((page - 1) * PageSize)
.Take(PageSize));
}
}

}
Các field PageSize xác định rằng tôi muốn bốn sản phẩm mỗi trang. Tôi sẽ quay trở lại và thay thế điều này với
một cơ chế tốt hơn sau này. Tôi đã thêm một tham số tùy chọn (optional parameter) cho phương thức List. Điều này
có nghĩa rằng nếu tôi gọi phương thức mà không có một tham số (List()), lời gọi của tôi được đối xử như là tôi đã
cung cấp giá trị quy định trong định nghĩa tham số (List(1)). Hiệu quả là việc phương thức hành động hiển thị
trang đầu tiên của các sản phẩm khi MVC Framework gọi nó mà không có một argument. Trong phần thân của phương
thức, tôi nhận được các đối tượng Product, sắp xếp chúng bằng các khóa chính, bỏ qua các sản phẩm mà xuất hiện
trước khi khởi động trang hiện tại, và lấy số lượng sản phẩm theo quy định của field PageSize.

UNIT TEST: PHÂN TRANG
Tôi có thể unit test cho tính năng phân trang bằng cách tạo ra một mock repository, chèn nó vào trong constructor
của lớp ProductController, và sau đó gọi phương thức List để yêu cầu một trang cụ thể. Sau đó tôi
có thể so sánh các đối tượng Product mà tôi nhận được với những gì tôi mong đợi từ dữ liệu test trong mock
implementation. Xem Chương 6 để biết chi tiết làm thế nào để thiết lập các unit test. Dưới đây là unit test mà tôi
tạo ra cho mục đích này, trong file UnitTest1.cs của project SportsStore.UnitTests:

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SportsStore.Domain.Abstract;
using SportsStore.Domain.Entities;
using SportsStore.WebUI.Controllers;
namespace SportsStore.UnitTests {
[TestClass]


×