.Net Fluent Validation mengatur urutan eksekusi

Saya perlu mengatur urutan eksekusi untuk validasi sehingga berhenti memvalidasi setelah kegagalan pertama.

Namun ini tidak tersedia, jadi saya ingin tahu cara lain apa untuk melakukan ini.

Biasanya saya akan memiliki sesuatu seperti ini:

public Constructor(){

    // Simple validation
    RuleFor(x => x.Id).NotNull().NotEmpty();

    // advanced validation
    // item must exist in database
    RuleFor(x => x.Id).Must(ExistsInDatabase);

    // item must exist in database previously
    // item must be some of the allowed names -- fetched from db
    RuleFor(x => x.Id).Must(BeAReferenceInSomeTable);

    private bool ExistsInDatabase(){}

    private bool BeAReferenceInSomeTable(){}

}

Namun dengan ini BeAReferenceInSomeTable dapat dieksekusi sebelum ExistsInDatabase. Jadi validasi BeAReferenceInSomeTable akan memunculkan pengecualian ketika Id tidak ada dalam tabel alih-alih validasi gagal karena validasi ExistsInDatabase.

Untuk mengatasinya pertama yang terlintas dalam pikiran adalah seperti ini:

public Constructor(){

    CascadeMode = FluentValidation.CascadeMode.StopOnFirstFailure;

    // simple validation stays the same
    ...

    // advanced validation
    RuleFor(x => x.Id)
        .Must(ExistsInDatabase)
        .Must(BeAReferenceInSomeTable)
        .When(x => !string.IsNullOrEmpty(x.Id) &&
                    !string.IsNullOrEmpty(x.Name)
        );  
}

Namun dalam kasus ini bagaimana cara menetapkan pesan yang tepat untuk validasi karena pesan harus diberikan sebelum dieksekusi.


person Matija K.    schedule 12.06.2014    source sumber
comment
Anda dapat menggunakan .WithMessage("your message"); untuk menambahkan pesan yang tepat untuk kegagalan validasi, dan ini juga berfungsi dengan rangkaian (yang Anda lakukan pada contoh kedua).   -  person Moo    schedule 12.06.2014
comment
Ya tetapi ExistsInDatabase harus kembali: Id tidak ada catatan di database dan BeAReference harus kembali: Id tidak direferensikan di beberapa tabel. Dengan WithMessage hanya mungkin untuk meneruskan string statis yang telah ditentukan sebelumnya. Tapi ini kurang bagus karena saya hanya ingin 1 pesan dibalas   -  person Matija K.    schedule 12.06.2014


Jawaban (1)


Cobalah sesuatu seperti ini:

public Constructor(){

    // Simple validation
    RuleFor(x => x.Id).Cascade(CascadeMode.StopOnFirstFailure).NotNull().WithMessage("Must not be null");

    RuleFor(x => x.Id).NotEmpty().WithMessage("Must not be empty");


    // advanced validation
    // item must exist in database
    RuleFor(x => x.Id).Must(ExistsInDatabase).WithMessage("Must exist in database");

    // item must exist in database previously
    // item must be some of the allowed names -- fetched from db
    RuleFor(x => x.Id).Must(BeAReferenceInSomeTable).WithMessage("Must not be referenced");

    private bool ExistsInDatabase(){}

    private bool BeAReferenceInSomeTable(){}

}

Dan dirantai untuk perintah eksekusi:

RuleFor(x => x.Id).Cascade(CascadeMode.StopOnFirstFailure)
    .NotNull().WithMessage("Must not be null")
    .NotEmpty().WithMessage("Must not be empty")
    .Must(ExistsInDatabase).WithMessage("Must exist in database")
    .Must(BeAReferenceInSomeTable).WithMessage("Must not be referenced");
person Moo    schedule 12.06.2014
comment
Saat Anda menyetel mode Cascade di baris pertama, mode ini hanya digunakan untuk rantai tersebut. Jadi menggunakannya tanpa beberapa kondisi tidak akan berpengaruh. Kode selanjutnya membawa saya ke masalah yang sama yang membuka topik. WithMessage yang Anda tambahkan akan menghasilkan kesalahan validasi yang benar tetapi validasi mungkin tidak dijalankan secara berurutan. - person Matija K.; 12.06.2014
comment
Kemudian gunakan rangkaian untuk mencapai perintah eksekusi. - person Moo; 12.06.2014
comment
Saya menyampaikan contoh Anda, dapatkan apa yang saya butuhkan tetapi ini melakukan operasi yang mubazir. Apakah menurut Anda ada cara yang lebih baik? Saya akan menandai solusi Anda sebagai solusi yang tepat karena mendekati (tetapi tidak cukup) dengan yang saya butuhkan. RuleFor(x =› x.Id).Must(ExistsInDatabase).WithMessage(Harus ada di database).When(x =› x.Id.NotNullOrEmpty()) RuleFor(x =› x.Id).Must(BeAReferenceInSomeTable) .WithMessage(Tidak boleh direferensikan).When(x =› x.NotNullOrEmpty() && ExistsInDatabase(x)); - person Matija K.; 12.06.2014
comment
Operasi mubazir apa yang sedang dilakukan? - person Moo; 12.06.2014
comment
Untuk validasi BeAReferenceInSomeTable ExistsInDatabase dijalankan sebelum validasi. Untuk validasi ExistsInDatabase metode yang sama dijalankan lagi. Ini bukan masalah untuk pengujian kecil ini, namun dapat diterapkan pada pengujian yang lebih besar. - person Matija K.; 12.06.2014
comment
Itu saja, bahkan tidak terpikir oleh saya bahwa Anda dapat menambahkan banyak pesan seperti itu (saya berasumsi yang terakhir akan digunakan). Inilah jawaban yang saya cari. Terima kasih - person Matija K.; 12.06.2014