Xin thứ lỗi cho bài viết dài. Có một câu hỏi, chỉ cần chịu đựng với tôi.
Một bối cảnh nhỏ
Chúng tôi có một trang web được yêu cầu thích nghi đáng kể dựa trên nhiều cài đặt người dùng, nhóm người dùng thuộc về, nơi họ đến và những thứ khác. Chúng tôi thường bao gồm các bit có liên quan trên mô hình cho trang, vì vậy nếu trang có bảng sẽ hiển thị nếu người dùng trên một độ tuổi nhất định, thì trên mô hình chúng tôi sẽ làm một cái gì đó như:
//model
public PageModel
{
public bool ShowTable {get;set;}
}
//controller
public PageController
{
public ActionResult ShowPage()
{
var model = new PageModel() {
ShowTable = User.Age > 21
};
return View(model);
}
}
//view
@if(Model.ShowTable)
{
<table>Some Html here</table>
}
Điều này nhanh chóng trở nên rất phức tạp để biết những gì chúng ta nên hiển thị cho người dùng nào. Để thử và giải quyết vấn đề này, chúng tôi tập trung tất cả logic về thời điểm một thứ cụ thể sẽ được hiển thị hoặc ẩn đi. Chúng tôi đã gọi lớp này UserConfiguration
và nó (hầu hết) chỉ chứa một loạt các hàm trả về booleans chỉ ra những gì sẽ được hiển thị. Điều này cho phép chúng tôi thiết lập một loạt Thông số kỹ thuật và Thử nghiệm về những gì người dùng sẽ được hiển thị. Điều này UserConfigratuion
sau đó được đưa vào một lớp cơ sở, mà tất cả các mô hình trang được yêu cầu kế thừa từ đó, vì vậy những gì chúng ta hiện đang có là như thế này:
//UserConfiguration
public UserConfiguration
{
private readonly User _user;
public UserConfiguration(User user) {
_user = user
}
public bool ShowTable() {
return _user.Age > 21;
}
}
//model base
public ModelBase
{
public UserConfiguration {get;set;}
}
//model
public PageModel : ModelBase
{
// whatever data is needed for the page
}
//controller
public PageController
{
public ActionResult ShowPage()
{
var userConfiguration = new UserConfiguration(User);
var model = new PageModel {
UserConfiguration = userConfiguration
};
return View(model);
}
}
//view
@if(Model.UserConfiguration.ShowTable())
{
<table>Some Html here</table>
}
Điều này đã giúp ích, chủ yếu là vì nó cho phép chúng tôi tạo ra một loạt các thử nghiệm về những gì người dùng nên và không nên xem, v.v. Tuy nhiên, đó không phải là một giải pháp rất sạch sẽ, phải kết hợp lớp bổ sung này và đưa nó vào mô hình. Nó cũng có các phân nhánh để hiển thị Chế độ xem một phần. Nếu mô hình có một thuộc tính IEnumerable<Foo> Foos
trên nó, mà chúng ta muốn kết xuất một phần, nhưng một phần đó cũng phụ thuộc vào cấu hình người dùng, chúng ta có một vấn đề. Bạn không thể chuyển các foos cho Partial như mô hình, bởi vì sau đó một phần không có quyền truy cập vào UserConfiguration
. Vì vậy, những gì sẽ là cách tốt nhất để truy cập thông tin này. Theo cách tôi thấy, trong ngữ cảnh của asp.net MVC, có 4 cách khả dụng:
1) Có một mô hình mới cho một phần, ví dụ
// parent view
@{
var foosModel = new foosModel {
Foos = Model.Foos,
UserConfiguration = Model.UserConfiguration
}
}
@Html.RenderPartial("FooList", foosModel)
// child partial view
@if(Model.UserConfiguration.ShowTable) {
foreach(var foo in Model.Foos) {
//Some HTML
}
}
Đây có lẽ là giải pháp "thuần túy nhất", tuân thủ tốt nhất các nguyên tắc của MVC, nhưng liên quan đến rất nhiều mô hình (được cho là không cần thiết), gây ra sự phình to của dự án.
2) Hiển thị Cấu hình người dùng thông qua ViewData. ví dụ :
// parent view
@Html.RenderPartial("FooList", Model.Foos, new ViewDataDictionary { { "UserConfiguration", Model.UserConfiguration } })
// child partial view
@{
var userConfig = (UserConfiguration)ViewData["UserConfiguration"];
}
@if(userConfig.ShowTable) {
foreach(var foo in Model) {
//Some HTML
}
}
Tôi không thực sự thích điều này bởi vì nó không phải là loại an toàn và dựa vào chuỗi ma thuật để lấy nó từ ViewData.
3) Đặt cấu hình người dùng trong ViewBag. Vấn đề tương tự như trên thực sự
4) Sửa đổi mô hình trang và hiển thị Cấu hình người dùng thông qua một thuộc tính của chính trang đó, theo http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view .aspx /
Tôi cảm thấy vì UserConfiguration là thông tin theo ngữ cảnh xung quanh, nên có ý nghĩa để hiển thị nó thông qua lớp như trong tùy chọn 4 ở trên. Có thường được chấp nhận thực hành tốt nhất trong MVC để hiển thị loại dữ liệu này? Có ai đã thử bất cứ điều gì như tùy chọn 4 trong quá khứ và có bất kỳ 'gotcha' nào không
tl; dr: Cách tốt nhất để hiển thị thông tin theo ngữ cảnh cho các chế độ xem trên trang web của bạn, trong MVC nói chung hoặc asp.net MVC nói riêng là gì?