1. Trang chủ
  2. » Tất cả

11.Chuong 11

28 3 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 28
Dung lượng 1,15 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Adding CatalogManagement Thêm tính năng quản lý danh mục Quy ước cho quản lý những bộ các item là biểu diễn đến user với 2 kiểu trang: list page và edit page như trong hình 11-1 Figure

Trang 1

Adding CatalogManagement

(Thêm tính năng quản lý danh mục)

Quy ước cho quản lý những bộ các item là biểu diễn đến user với 2 kiểu trang: list page và edit page như trong hình 11-1

Figure 11-1 Sketch of a CRUD UI for the productcatalog

Kết hợp với nhau, những trang này cho phép người dùng tạo, xem và update các item trong collection.Một cách tổng hợp, những hoạt động này gọi là CRUD Những người phát triển cần thực hiện CRUD thương xuyên nên VS cố gắng giúp họ bằng cách phát sinh những controllers có các action method cho hoạt động CRUD và view template để hỗ trợ nó Nhưng cũng như mọi VS template , tôi nghĩ tốt hơn vẫn nên học cách sử dụng tính năng đó của MVC Framework một cách trực tiếp

Creating a CRUDController

(Tạo một CRUD controller)

Tôi sẽ tạo một controller mới cho tính năng quản trị SportStore.Chuột phải vào Controllers folder trong SportStore.WebUI project trong Solution Explorer và chọn Add>Controller trong pop-up menu.Chọn MVC 5 Controller – Empty trong danh sách lựa chọn Nhấn Add, đặt tên là AdminController và nhấn Add để tạo file Controller/AdminController.cs Sửa nội dung trong class controller cho giống với list 11-1

usingSystem.Web.Mvc;

using SportsStore.Domain.Abstract;

namespace SportsStore.WebUI.Controllers{

Trang 2

public class AdminController : Controller {

UNIT TEST: THE INDEXACTION

Hành vi chúng ta quan tâm về hàm Index của Admin controller là nó trả về chính xác Product object trong vùng lưu trữ Chúng ta có thể kiểm thử điều này bằng cách tạo một vùng lưu trữ giả thực thi và so sánh dữ liệu kiểm thử so sánh với dữ liệu trả về vởi action method Sau đây là unit test, tôi đặt nó vào trong một file unit test mới gọi là AdminTests.cs trong SportStore.UnitTest project

// Arrange - create the mock repository

Mock<IProductRepository>mock = new Mock<IProductRepository>(); mock.Setup(m =>m.Products).Returns(new Product[]{

newProduct {ProductID = 1, Name = "P1"}, new Product {ProductID = 2, Name = "P2"}, new Product {ProductID = 3, Name ="P3"}, });

// Arrange - create acontroller

AdminController target = newAdminController(mock.Object);

//Action

Product[] result =((IEnumerable<Product>)target.Index()

ViewData.Model).ToArray();

//Assert

Trang 3

(Tạo một layout mới)

Chúng ta sẽ tạo một layout mới để dùng cho view của chức năng quản trị trong SportStort Đây sẽ là một layout đơn giản cung cấp một nơi chúng ta có thể đặt những thay đổi vào trong các view quản trị

Tạo một layout mới bằng cách chuột phải vào Views/Shared folder trong SportsStore.WebUI project và chọn Add> MVC 5 Layout Page(Razor) trong pop-up menu Đặt tên là _AdminLayout.cshtml (đừng quên gạch chân) và nhấn nút OK để tạo file Views/Shared/_AdminLayout.cshtml Chỉnh lại nội dung của file cho khớp với List 11-2

Chú ý: Như tôi đã giải thích từ trước, quy ước đối với tên layout là bắt đầu với dấu gạch dưới (_) Razor cũng được dùng bởi một công nghệ của Microsoft khác tên là WebMatrix, vốn dùng dấu gạch dưới để ngăn các trang layout được chuyển đến browser MVC thì không vần sự nảo vệ này nhưng quy ước đặt tên này vẫn được chuyển lên ứng dụng MVC

<meta name="viewport" content="width=device-width"/>

<link href="∼/Content/bootstrap.css" rel="stylesheet"/>

<link href="∼/Content/bootstrap-theme.css" rel="stylesheet"/>

<link href="∼/Content/ErrorStyles.css" rel="stylesheet"/>

Thực thi List View

Bây giờ khi chúng ta đã có layout mới, chúng ta có thể thêm một view vào project cho Index action method của Admin controller Ngay cả khi tôi không phải là một fan của tính năng dựng bộ khung (scaffold) template có sẵn trong Visual Studio, tôi cũng sẽ vẫn tạo một view mới cho hàm Index dùng hệ thống scaffolding để chúng ta có thể thấy cách nó hoạt động Chỉ vì chúng ta không

Trang 4

thích những đoạn code cắt sẵn, không có nghĩa là chúng ta không nên sử dụng nó

Chuột phải vào folder Views/Admin trong project SportStore.WebUI và chọ,n Add>View trong menu Đặt tên view là Index, chọn List trong mục Template (đây là mục tôi thường đặt ở mục Empty), chọn Product trong Model Class, check chọn vào nút dùng layout page, chọn file _AdminLayout.cshtml trong Views/Shared folder Theo dõi cấu hình như trong hình 11-2

Figure 11-2 Configuring a scaffoldview

Chú ý: khi dùng tính năng List scaffold, VS giả định rằng chúng ta đang làm việc trên dãy IENumerable của model view type vì thế chúng ta chỉ nên chọn dạng đơn của form của class trong list

Note When using the List scaffold, Visual Studio assumes you are working with an IEnumerable sequence of the

model view type, so you can just select the singular form of the class from the list

Nhấn nút Add để tạo view mới, nội dung của nó sẽ giống như trong List 11-3 (Tôi đã định mạng lại các markup để nó không chiếm nhiều diện tích của trang )

Trang 5

@Html.ActionLink("Edit", "Edit", new { id=item.ProductID })|

@Html.ActionLink("Details", "Details", new {id=item.ProductID

@Html.ActionLink("Delete", "Delete", new { id=item.ProductID

</td>

</tr>

Trang 6

</table>

VS tìm trong kiểu của đối tượng view model và phát sinh ra các element trong một bảng liên quan đến các thuộc tính được định

nghĩa bởi kiểu model Chúng ta có thể thấy cách mà view được dựng nên bằng cách chạy ứng dụng và điều hướng cho nó đến

/Admin/Index Hình 11-3 miêu tả kết quả

Figure 11-3 Rendering the scaffold Listview

Scafold view cố gắng tạo ra một cấu hình hợp lý dựa trên cơ sở của view Chúng ta có các cột cho mỗi thuộc tính trong lớp Product và nối đến các tác vụ trong CRUD dẫn đến các action method trong Admin controller (tuy nhiên, từ lúc chúng ta tạo controller không hề sử dụng tính năng scafolding nên action method sẽ không tồn tại )

Tính năng Scafolding rất khéo léo nhưng view do nó phát sinh ra đơn giản và bình thương không hề đáng có với project có độ phức tạp Lời khuyên là chúng ta nên bắt đầu với một controller rỗng (empty controller), views cũng như layout và thêm tính năng chúng ta cần vào khi cần thiết

Trở về với hướng tiếp cận tự mình thực hành, thay đổi file Index.cshtml như trong List 11-4

Trang 7

@Html.ActionLink("Add a new product", "Create", null,

new { @class = "btn btn-default"})

</div>

</div>

View này thể hiện thông tin của form chắc chắn hơn, bỏ qua một số thuộc tính trong lớp Product và dùng Boostrap để đặt

thông số về style Chúng ta có thể xem cách view được dựng lên như trong hình 11-4

Trang 8

Figure 11-4 Rendering the modified Indexview

Bây giờ chúng ta đã có một trang danh sách ổn.Quản trị viên có thể thấy các product trong catalog và có các nút để thêm xóa và kiểm tra thông tin Trong phần tiếp theo chúng ta sẽ thêm chức năng để hỗ trợ cho từng hoạt động đó

Now I have a nice list page The administrator can see the products in the catalog and there are links or buttons to add, delete, and inspect items In the following sections, I will add the functionality to support each of these actions

Sửa thông tin Products

Để cung cấp tính năng tạo và sửa , chúng ta sẽ thêm trang cho phép sửa thông tin tương tự như hình 11 -1 Công việc này chia thành hai phần

Hiển thị một trang cho phép người quản trị thay đổi giá trị thuộc tính của product

Thêm một action method có thể xử lý các thay đổi khi chúng được submit (gửi đi)

Trang 9

9

Tạo Edit action method

List 11-5 là nội dung Edit method được thêm vào trong Admin controller Đây là action method chúng ta định ra trong lời lời gọi đến công cụ hỗ trợ Html.ActionLink torng Index view

public ViewResult Edit(int productId) {

Product product =repository.Products FirstOrDefault(p =>p.ProductID == productId);

UNIT TEST: THE EDIT ACTIONMETHOD

Tôi muốn kiểm thử hành vi trong Edit action method Trước tiên là tôi lấy sản phẩm mà tôi yêu cầu khi cung cấp một ID có tồn tại Rõ ràng chúng ta muốn đảm bảo rằng chúng ta đang sửa đúng product mà chúng ta mong muốn Hành vi thứ hai là tôi không lấy bất kỳ sản phẩm nào khi yêu cầu một ID không có trong vùng lưu trữ Sau đây là hàm kiểm thử thêm vào trong file test AdminTest.cs

[TestMethod]

publicvoid Can_Edit_Product(){

// Arrange - create the mock repository

Mock<IProductRepository>mock = new Mock<IProductRepository>();

mock.Setup(m =>m.Products).Returns(new Product[]{

newProduct {ProductID = 1, Name = "P1"},

new Product {ProductID = 2, Name = "P2"},

new Product {ProductID = 3, Name ="P3"},

});

// Arrange - create thecontroller

AdminController target = newAdminController(mock.Object);

Trang 10

//Act

Product p1 = target.Edit(1).ViewData.Model as Product;

Product p2 = target.Edit(2).ViewData.Model as Product;

Product p3 = target.Edit(3).ViewData.Model asProduct;

// Arrange - create the mock repository

Mock<IProductRepository>mock = new Mock<IProductRepository>();

mock.Setup(m =>m.Products).Returns(new Product[]{

newProduct {ProductID = 1, Name = "P1"},

new Product {ProductID = 2, Name = "P2"},

new Product {ProductID = 3, Name ="P3"},

});

// Arrange - create thecontroller

AdminController target = newAdminController(mock.Object);

Creating the EditView

Bây giờ khi đã có action method, chúng ta có thể tạo một view để dựng nên Chuột phải vào folder Views/Admin trong Solution Explorer rồi chọn Add>MVC5 View Page (Razor) trong phần menu Đặt tên thành Edit.cshtml, nhấn nút để tạo file và thay đổi nội dung như trong List 11-6

<input type="submit" value="Save"/>

@Html.ActionLink("Cancel and return to List","Index")

Trang 11

11

}

Thay vì viết markup cho mỗi labels và input bằng tay Chúng ta gọi đến hàm trợ giúp Html.EditorForModel Hàm trợ giúp này yêu cầu MVC Framework tạo ra giao diện editing cho chúng ta bằng cách kiểm tra model type, trong trường hợp này là class Product Để xem trang được tạo ra như thế nào từ Edit view, chạy ứng dụng và điều ướng đến /Admin/Index Click một trong số các tên product và chúng ta nhận được một trang như trong hình 11-5

Figure 11-5 The page generated using the EditorForModel helpermethod

Thành thật mà nói, hàm EditorForModel tiện lợi nhưng nó lại không cho ra kết quả tốt nhất Thêm vào đó, chúng ta không muốn quản trị viên thấy hoặc sửa đổi thuộc tính ProductID, và phần textbox cho thuộc tính Description quá nhỏ

Chúng ta có thể chỉ dẫn cho MVC Framework cách để tạo phần edit cho các thuộc tính bằng cách sử dụng model metadata Nó cho phép áp các tính chất vào trong thuộc tính của lớp model mới để tạo tác động lên giá trị xuất của hàm Html.EditForModel List 11-7 cho thấy cách dùng metadata trong lớp Product trong project SportStore

public int ProductID { get; set; }

public string Name { get; set;}

[DataType(DataType.MultilineText)]

public string Description { get; set; }

public decimal Price { get; set;}

public string Category { get; set;}

}

Trang 12

}

Thuộc tính HiddenInput báo cho MVC Framwork dựng thuộc tính như một element ẩn (hidden element) và thuộc tính DataType cho phép xác định cách giá trịđược biểu diễn và thay đổi.Trong trường hợp này, tôi đã chọn MultilineText Thuộc tính

HiddenInput là một phần trong namespace System.Web.Mvc và thuộc tinh DataType là một phần trong namespace

System.ComponentModel.DataAnnotations, đó là lý do vì sao tôi yêu cầu nên thêm refference của các assembly này cho các namespace trong project SportStore trong chương 7

Hình 11-6 là kết quả khi đã thiết lập metadata, chúng ta không còn thấy hoặc có thể thay đổi thuộc tính ProductId, đồng thời cũng có một text box nhiều dòng trong phần miêu tả (description.)Tuy nhiên về tổng quan thì giao diện trông vẫn còn nghèo nàn

Figure 11-6 The effect of applyingmetadata

Vấn đề ở đây là công cụ trợ giúp Html.EditorForModel không hề có thông tin về lớp Prouct và phát sinh một số đoạn HTML

cơ bản và an toàn Có ba cách để giải quyết vấn đề này Vấn đề đầu tiên là xác định CSS style cho nội dung mà công cụ trợ giúp phát sinh, điều này giúp công việc dễ dàng hơn do các lớp được tự động thêm vào các HTML elements bởi MVC Framework Nếu như chúng ta nhìn vào đoạn mã nguồn cho hình 11-6, chúng ta sẽ thấy phần element textarea được tạo cho miêu tả product (product description) được gán cho lớp text-box-multi-line trong CSS

<textarea class="text-box-multi-line" id="Description"name="Description">

Các element HTML khác được gán các lớp giống nhau và chúng ta có thể tạo CSS style cho chúng Cách tiếp cận này hoạt động tốt khi chúng ta tạo ra một style tùy chỉnh nhưng nó không dễ để ứng dụng vào các lớp định trước như các lớp mà

Bootstrap định nghĩa

Hướng tiếp cận thứ 2 là cung cấp công cụ hỗ trợ với bằng templates cho phép khởi tạo các elements bao gồm cả các style chúng ta yêu cầu Hướng tiếp cần này sẽ được đề cập trong chương 22

Hướng tiếp cập thứ 3 là tạo các elements cần có một cách trực tiếp mà không dùng công cụ hàm hỗ trợ mức model Tôi thích

ý tưởng về hỗ trợ model nhưng lại hiếm khi dùng đến nó, tôi thích tự tạo HTML và dùng các hàm hỗ trợ cho từng thuộc tính đơn lẻ như trong List 11-8

Trang 13

@if (property.PropertyName == "Description"){

<input type="submit" value="Save" class="btnbtn-primary"/>

@Html.ActionLink("Cancel and return to List", "Index", null,

@class = "btnbtn-default"

})

</div>

Đây là kỹ thuật thay đổi metadata chúng ta đã sử dụng trong chương 9 và nó là một kỹ thuật mà bản thân tôi dùng thường

xuyên, dù cho tôi vẫn đạt được cùng một kết quả khi dùng hàm hỗ trợ cho HTML với kỹ thuật điều chỉnh mà chúng ta sẽ dùng trong chương 22 Có vài điểm trong cách tiếp cận này gắn liền với phong cách phát triển phần mềm của tôi nhưng với MVC

Framework, còn có nhiều hướng tiếp cận khách, các bạn có thể dùng nếu việc xử lý metadata không thực hiện công việc giúp bạn Chúng ta có thể thấy cách view được trình bày trên browser trong hình 11-7

Trang 14

Figure 11-7 Displaying the editor page forproducts

Updating the ProductRepository

Trước khi chúng ta có thể xử lý các thay đổi, tôi cần nâng cấp vùng lưu product cho phép nó các khả năng lưu những thay đổi Đầu tiên chúng ta thêm method mới vào IProductRepository interfaces như trong list 11-9 (để nhắc lại, chúng ta có thể thấy interface này trong folder Abstract trong project SportStore.Domain)

Before I can process edits, I need to enhance the product repository so that it is able to save changes First, I will add a new method

to the IProductRepository interface, as shown in Listing 11-9 (As a reminder, you will find this interface in the

using System.Collections.Generic;

usingSportsStore.Domain.Entities;

Trang 15

Chúng ta sau đó có thể thêm method mới vào trong việc thực thi của Entity Framework đối với vùng lưu trữ, định nghĩa

trong Concrete/EFProductRepository.cs file như trong List 11-10

using SportsStore.Domain.Abstract;

using SportsStore.Domain.Entities;

usingSystem.Collections.Generic;

namespace SportsStore.Domain.Concrete{

public class EFProductRepository : IProductRepository {

private EFDbContext context = newEFDbContext();

public IEnumerable<Product> Products {

get { return context.Products;}

}

publicvoid SaveProduct(Product product){

if(product.ProductID == 0) { context.Products.Add(product);

} else{

context.Products.Find(product.ProductID);

if(dbEntry != null) { dbEntry.Name =product.Name;

Ngày đăng: 23/10/2019, 21:15

TỪ KHÓA LIÊN QUAN

w