IValidatableObject vs Tanggung Jawab Tunggal

12

Saya suka titik ekstensi MVC, memungkinkan model tampilan untuk mengimplementasikan IValidatableObject, dan menambahkan validasi khusus.

Saya mencoba membuat Controllers tetap ramping, memiliki kode ini menjadi satu-satunya logika validasi:

if (!ModelState.IsValid)
    return View(loginViewModel);

Misalnya model tampilan masuk mengimplementasikan IValidatableObject, mendapatkan objek ILoginValidator melalui injeksi konstruktor:

public interface ILoginValidator
{
    bool UserExists(string email);
    bool IsLoginValid(string userName, string password);
}

Tampaknya Ninject, menyuntikkan contoh dalam model tampilan bukan benar-benar praktik umum, bahkan mungkin anti-pola?

Apakah ini pendekatan yang baik? Apakah ada yang lebih baik?

Boris Yankov
sumber
Jika Anda ingin validasi dalam objek yang terpisah, coba FluentValidation. Lihat fluentvalidation.codeplex.com/wikipage?title=mvc .
rmac
+1 Ide bagus untuk menyuntikkan kelas Validator terpisah, yang menyelesaikan masalah saya di mana saya harus mengakses informasi basis data untuk validasi!
Magnattic

Jawaban:

7

Secara pribadi, bagi saya desain Anda tampak bersih.

IValidatableObject berarti model tampilan akan memberikan beberapa validasi yang tidak dapat disediakan oleh atribut sederhana - menyuntikkan validator nyata yang akan memanggil layanan / database / apa pun yang membuat desain Anda tetap bersih dan memastikan Anda tidak melanggar prinsip tanggung jawab tunggal - View Models bertanggung jawab, pada dasarnya, untuk mentransfer data dan memvalidasi data yang ditransfer (apakah itu melalui atribut atau IValidatableObject atau keduanya).

David_001
sumber
4

Memiliki objek khusus untuk validasi menjamin bahwa Anda benar-benar menghormati SRP - yang memang sudah menjadi masalah karena merupakan tanggung jawab khas model tampilan untuk memvalidasi datanya.

Sedangkan untuk menyuntikkan instance ke model tampilan, saya tidak bisa melihat ada yang salah dengan itu. Hampir tidak ada batasan untuk apa yang bisa disuntikkan ke dalam apa.

guillaume31
sumber
3

Alih-alih menyuntikkan ILoginValidator ke konstruktor VM Anda, Anda dapat menggunakan ValidationContext (yang merupakan arg ke IValidatableObject.Validate ()) untuk mendapatkan Validator Anda.

public IEnumerable<ValidationResult> Validate(ValidationContext vc)
{

var loginValidator = (ILoginValidator)vc.GetService(typeof(ILoginValidator));
return loginValidator.Validate();

}
Kelly
sumber