Saya memiliki proses pendaftaran multi-langkah , yang didukung oleh satu objek di lapisan domain , yang memiliki aturan validasi yang ditentukan pada properti.
Bagaimana cara memvalidasi objek domain saat domain dibagi di banyak tampilan, dan saya harus menyimpan sebagian objek di tampilan pertama saat diposting?
Saya berpikir untuk menggunakan Sesi tetapi itu tidak mungkin karena prosesnya lama dan jumlah datanya tinggi, Jadi saya tidak ingin menggunakan sesi.
Saya berpikir untuk menyimpan semua data dalam db dalam memori relasional (dengan skema yang sama dengan db utama) dan kemudian membuang data itu ke db utama tetapi masalah muncul karena saya harus merutekan antar layanan (diminta dalam tampilan) yang bekerja dengan db utama dan db dalam memori.
Saya mencari solusi yang elegan dan bersih (lebih tepatnya praktik terbaik).
PEMBARUAN DAN Klarifikasi:
@Darin Terima kasih atas balasan Anda yang bijaksana, Itulah yang telah saya lakukan sampai sekarang. Tapi kebetulan saya mendapat permintaan yang memiliki banyak lampiran di dalamnya, saya mendesain Step2View
misalnya pengguna mana yang dapat mengunggah dokumen di dalamnya secara asinkron, tetapi lampiran itu harus disimpan dalam tabel dengan relasi referensial ke tabel lain yang seharusnya disimpan sebelumnya di Step1View
.
Jadi saya harus menyimpan objek domain di Step1
(sebagian), Tapi saya tidak bisa, karena objek Core Domain yang didukung yang dipetakan sebagian ke ViewModel Step1 tidak dapat disimpan tanpa props yang berasal dari konversi Step2ViewModel
.
sumber
Jawaban:
Pertama, Anda tidak boleh menggunakan objek domain apa pun dalam tampilan Anda. Anda harus menggunakan model tampilan. Setiap model tampilan hanya akan berisi properti yang diperlukan oleh tampilan yang diberikan serta atribut validasi khusus untuk tampilan yang diberikan ini. Jadi jika Anda memiliki wizard 3 langkah, ini berarti Anda akan memiliki 3 model tampilan, satu untuk setiap langkah:
dan seterusnya. Semua model tampilan tersebut dapat didukung oleh model tampilan wizard utama:
maka Anda bisa memiliki tindakan pengontrol yang merender setiap langkah dari proses wizard dan meneruskan main
WizardViewModel
ke tampilan. Saat Anda berada di langkah pertama di dalam tindakan pengontrol, Anda dapat menginisialisasiStep1
properti. Kemudian di dalam tampilan Anda akan menghasilkan formulir yang memungkinkan pengguna untuk mengisi properti tentang langkah 1. Saat formulir dikirimkan, tindakan pengontrol akan menerapkan aturan validasi untuk langkah 1 saja:Sekarang di dalam tampilan langkah 2 Anda bisa menggunakan Html.Serialize helper dari MVC futures untuk membuat serialisasi langkah 1 ke dalam bidang tersembunyi di dalam formulir (semacam Kondisi Tampilan jika Anda mau):
dan di dalam tindakan POST langkah2:
Begitu seterusnya hingga Anda mencapai langkah terakhir di mana Anda akan
WizardViewModel
diisi dengan semua data. Kemudian Anda akan memetakan model tampilan ke model domain Anda dan meneruskannya ke lapisan layanan untuk diproses. Lapisan layanan mungkin melakukan aturan validasi itu sendiri dan seterusnya ...Ada juga alternatif lain: menggunakan javascript dan meletakkan semua di halaman yang sama. Ada banyak plugin jquery di luar sana yang menyediakan fungsionalitas wizard ( Stepy bagus). Ini pada dasarnya adalah masalah menampilkan dan menyembunyikan div pada klien sehingga Anda tidak perlu lagi khawatir tentang status persisten di antara langkah-langkah tersebut.
Tapi apa pun solusi yang Anda pilih, selalu gunakan model tampilan dan lakukan validasi pada model tampilan tersebut. Selama Anda menempelkan atribut validasi anotasi data pada model domain Anda, Anda akan berjuang sangat keras karena model domain tidak disesuaikan dengan tampilan.
MEMPERBARUI:
Oke, karena banyaknya komentar saya menarik kesimpulan bahwa jawaban saya tidak jelas. Dan saya harus setuju. Jadi izinkan saya mencoba mengembangkan contoh saya lebih jauh.
Kita bisa mendefinisikan antarmuka yang harus diterapkan oleh semua model tampilan langkah (ini hanya antarmuka penanda):
kemudian kami akan menentukan 3 langkah untuk wizard di mana setiap langkah tentu saja hanya akan berisi properti yang diperlukan serta atribut validasi yang relevan:
selanjutnya kita mendefinisikan model tampilan wizard utama yang terdiri dari daftar langkah-langkah dan indeks langkah saat ini:
Kemudian kita beralih ke pengontrol:
Beberapa komentar tentang pengontrol ini:
[Deserialize]
atribut dari pustaka Microsoft Futures jadi pastikan Anda telah menginstalMvcContrib
NuGet. Itulah alasan mengapa model tampilan harus didekorasi dengan[Serializable]
atributIStepViewModel
antarmuka sehingga agar masuk akal kita memerlukan pengikat model kustom.Berikut pengikat model terkait:
Binder ini menggunakan bidang tersembunyi khusus yang disebut StepType yang akan berisi tipe konkret dari setiap langkah dan yang akan kami kirimkan pada setiap permintaan.
Pengikat model ini akan didaftarkan di
Application_Start
:Bagian terakhir dari teka-teki yang hilang adalah pandangannya. Berikut
~/Views/Wizard/Index.cshtml
tampilan utamanya :Dan hanya itu yang Anda butuhkan agar ini berhasil. Tentu saja jika Anda mau, Anda dapat mempersonalisasi tampilan dan nuansa beberapa atau semua langkah wizard dengan menentukan template editor kustom. Misalnya mari kita lakukan untuk langkah 2. Jadi kita mendefinisikan
~/Views/Wizard/EditorTemplates/Step2ViewModel.cshtml
parsial:Seperti inilah strukturnya:
Tentu masih ada ruang untuk perbaikan. Tindakan Indeks POST terlihat seperti s..t. Terlalu banyak kode di dalamnya. Penyederhanaan lebih lanjut akan melibatkan pemindahan semua hal infrastruktur seperti indeks, manajemen indeks saat ini, penyalinan langkah saat ini ke wizard, ... ke pengikat model lain. Sehingga akhirnya kita mendapatkan:
yang lebih merupakan tampilan tindakan POST. Saya meninggalkan perbaikan ini untuk waktu berikutnya :-)
sumber
Untuk melengkapi jawaban Amit Bagga, Anda akan menemukan apa yang saya lakukan di bawah ini. Meskipun kurang elegan, saya menemukan cara ini lebih sederhana daripada jawaban Darwin.
Pengontrol:
Model:
sumber
Saya menyarankan Anda untuk mempertahankan status Proses Lengkap pada klien menggunakan Jquery.
Dengan cara ini Anda dapat dengan mudah membangun objek domain Anda langsung dari data formulir posting dan jika data memiliki kesalahan, kembalikan JSON yang valid yang menahan semua pesan kesalahan dan menampilkannya dalam sebuah div.
Harap pisahkan Langkah-langkahnya
sumber
Wizard hanyalah langkah sederhana dalam memproses model sederhana. Tidak ada alasan untuk membuat beberapa model untuk wizard. Yang akan Anda lakukan hanyalah membuat model tunggal dan meneruskannya di antara tindakan dalam satu pengontrol.
Mahasiswa di atas bodoh sederhana jadi gantilah bidang Anda di sana. Selanjutnya kita mulai dengan tindakan sederhana yang memulai wizard kita.
Ini memanggil tampilan "WizardStep1.cshtml (jika menggunakan pisau cukur). Anda dapat menggunakan wizard buat template jika Anda mau. Kami hanya akan mengarahkan posting ke tindakan yang berbeda.
Hal yang perlu diperhatikan adalah kami akan memposting ini ke tindakan yang berbeda; tindakan WizardStep2
Dalam tindakan ini kami memeriksa apakah model kami valid, dan jika demikian kami mengirimkannya ke tampilan WizardStep2.cshtml kami yang lain kami kirimkan kembali ke langkah pertama dengan kesalahan validasi. Di setiap langkah kami mengirimkannya ke langkah berikutnya, memvalidasi langkah itu dan melanjutkan. Sekarang beberapa pengembang yang paham mungkin berkata baik kita tidak dapat berpindah di antara langkah-langkah seperti ini jika kita menggunakan atribut [Wajib] atau anotasi data lainnya di antara langkah-langkah tersebut. Dan Anda akan benar, jadi hapus kesalahan pada item yang belum diperiksa. seperti dibawah ini.
Akhirnya kita akan menyimpan model sekali ke penyimpanan data. Ini juga mencegah pengguna yang memulai panduan tetapi tidak menyelesaikannya untuk tidak menyimpan data yang tidak lengkap ke database.
Saya harap metode penerapan wizard ini jauh lebih mudah digunakan dan dipelihara daripada metode yang disebutkan sebelumnya.
Terima kasih sudah membaca.
sumber
Saya ingin berbagi cara saya menangani persyaratan ini. Saya tidak ingin menggunakan SessionState sama sekali, saya juga tidak ingin menangani sisi klien, dan metode serialisasi memerlukan MVC Futures yang tidak ingin saya sertakan dalam proyek saya.
Sebagai gantinya, saya membuat Pembantu HTML yang akan mengulangi semua properti model dan menghasilkan elemen tersembunyi khusus untuk masing-masing properti. Jika itu adalah properti yang kompleks maka itu akan berjalan secara rekursif di atasnya.
Dalam formulir Anda, mereka akan diposting ke controller bersama dengan data model baru di setiap langkah "wizard".
Saya menulis ini untuk MVC 5.
Sekarang untuk semua langkah "wizard" Anda, Anda dapat menggunakan model dasar yang sama dan meneruskan properti model "Step 1,2,3" ke dalam pembantu @ Html.HiddenClassFor menggunakan ekspresi lambda.
Anda bahkan dapat memiliki tombol kembali di setiap langkah jika Anda mau. Cukup memiliki tombol kembali di formulir Anda yang akan mengirimkannya ke tindakan StepNBack pada pengontrol menggunakan atribut formaction. Tidak termasuk dalam contoh di bawah ini tetapi hanya sebuah ide untuk Anda.
Bagaimanapun ini adalah contoh dasar:
Inilah MODEL Anda
Ini CONTROLLER Anda
Berikut adalah PANDANGAN Anda
Langkah 1
Langkah 2
LANGKAH 3
sumber
Menambah info lebih lanjut dari jawaban @ Darin.
Bagaimana jika Anda memiliki gaya desain terpisah untuk setiap langkah dan ingin mempertahankan masing-masing dalam tampilan parsial terpisah atau bagaimana jika Anda memiliki beberapa properti untuk setiap langkah?
Saat menggunakan
Html.EditorFor
kami memiliki batasan untuk menggunakan tampilan parsial.Buat 3 Tampilan Parsial di bawah
Shared
folder bernama:Step1ViewModel.cshtml , Step3ViewModel.cshtml , Step3ViewModel.cshtml
Singkatnya saya baru saja memposting tampilan patial pertama, langkah-langkah lainnya sama dengan jawaban Darin.
Step1ViewModel.cs
Step1ViewModel.cshtml
Index.cshtml
Jika ada solusi yang lebih baik, beri komentar untuk memberi tahu orang lain.
sumber
Salah satu opsinya adalah membuat sekumpulan tabel identik yang akan menyimpan data yang dikumpulkan di setiap langkah. Kemudian pada langkah terakhir jika semuanya berjalan dengan baik Anda dapat membuat entitas nyata dengan menyalin data sementara dan menyimpannya.
Lainnya adalah membuat
Value Objects
untuk setiap langkah dan menyimpannya kemudian diCache
atauSession
. Kemudian jika semuanya berjalan dengan baik Anda dapat membuat objek Domain Anda dari mereka dan menyimpannyasumber