Maafkan kiriman panjang. Ada pertanyaan, tetap saja bersamaku.
Konteks Kecil
Kami memiliki situs yang diharuskan untuk beradaptasi berdasarkan berbagai pengaturan pengguna, grup milik pengguna, dari mana mereka berasal dan hal-hal lain. Kami dulu memasukkan bit yang relevan pada model untuk halaman, jadi jika halaman memiliki tabel yang akan menunjukkan jika pengguna lebih dari usia tertentu, maka pada model kami akan melakukan sesuatu seperti:
//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>
}
Ini dengan cepat menjadi sangat rumit untuk mengetahui apa yang harus kami tunjukkan kepada pengguna mana. Untuk mencoba dan mengatasi masalah ini, kami memusatkan semua logika tentang kapan hal tertentu harus ditampilkan atau disembunyikan. Kami memanggil kelas ini UserConfiguration
dan itu (kebanyakan) hanya berisi serangkaian fungsi mengembalikan boolean yang menunjukkan apa yang harus ditampilkan. Ini memungkinkan kami untuk menyiapkan serangkaian Spesifikasi dan Tes tentang apa yang harus ditampilkan oleh pengguna. Ini UserConfigratuion
kemudian diletakkan di kelas dasar, yang mewarisi dari semua model halaman, jadi yang kita miliki saat ini adalah sesuatu seperti ini:
//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>
}
Ini telah membantu, sebagian besar karena memungkinkan kami untuk membuat serangkaian tes tentang apa yang harus dan tidak boleh dilihat oleh pengguna, dll. Namun, ini bukan solusi yang sangat bersih, harus mengumpulkan kelas tambahan ini dan memasukkannya pada model. Ini juga memiliki konsekuensi untuk menampilkan Tampilan Parsial. Jika model memiliki properti IEnumerable<Foo> Foos
di atasnya, yang ingin kami render secara parsial, tetapi sebagian itu juga bergantung pada konfigurasi pengguna, kami memiliki masalah. Anda tidak bisa hanya meneruskan foos ke Partial sebagai model, karena sebagian tidak memiliki akses ke UserConfiguration
. Jadi apa yang akan menjadi cara terbaik untuk mengakses informasi ini. Cara saya melihatnya, dalam konteks asp.net MVC ada 4 cara yang tersedia:
1) Memiliki model baru untuk contoh parsial
// 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
}
}
Ini mungkin solusi "paling murni", yang paling sesuai dengan prinsip-prinsip MVC, tetapi melibatkan banyak model (yang bisa dibilang tidak perlu), menyebabkan proyek menggembung.
2) Paparkan Konfigurasi Pengguna melalui ViewData. misalnya:
// 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
}
}
Saya tidak terlalu suka ini karena ini bukan tipe aman dan bergantung pada string ajaib untuk mendapatkannya dari ViewData.
3) Masukkan UserConfiguration di ViewBag. Masalah yang sama seperti di atas kok
4) Ubah model halaman, dan paparkan Konfigurasi Pengguna melalui properti halaman itu sendiri, sesuai http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view .aspx /
Saya merasa karena Konfigurasi Pengguna adalah informasi kontekstual ambient, masuk akal untuk mengeksposnya melalui kelas seperti pada opsi 4 di atas. Apakah ada praktik terbaik yang diterima secara umum di MVC untuk mengekspos data semacam ini? Adakah yang pernah mencoba sesuatu seperti opsi 4 di masa lalu dan apakah ada 'gotcha'
tl; dr: Apa cara terbaik untuk mengungkapkan informasi kontekstual ke tampilan di situs Anda, di MVC secara umum atau MVC asp.net pada khususnya?