2012-12-26 10 views
5

Obecnie ma konfigurację ViewModel jako takie:Walidacja Zagnieżdżone modele

public class OurViewModel 
    { 
     public OurViewModel() { } 

     [Required] 
     public int LeadID { get; set; } 
     [Required] 
     public int Rate { get; set; } 
     [Required] 
     public bool DepositRequired { get; set; } 
     [RequiredIfOtherPropertyIsTrue("DepositRequired")] 
     public BankInfo { get; set; } 
    } 

... W tym przypadku, „RequiredIfOtherPropertyIsTrue” to walidator że ma dość dużo, co jest napisane: sprawdza, czy inna nieruchomość prawdziwe (w tym przypadku nasza wartość logiczną wskazującą, czy wymagany jest depozyt) i BankInfo to kolejny model, który wygląda mniej więcej tak:

public class BankInfo 
{ 
    public enum AccountTypeEnum 
    { 
     CHECKING, 
     SAVINGS 
    } 

    public BankAccountInfo() { } 

    [DisplayName("Account Number")] 
    [Required(ErrorMessage = "You must provide a valid bank account number")] 
    public String AccountNumber { get; set; } 

    [DisplayName("Bank Routing Number")] 
    [Required(ErrorMessage = "You must provide a valid routing number")] 
    [StringLength(9, MinimumLength = 9, ErrorMessage = "Your bank routing number must be exactly 9 digits")] 
    public String ABANumber { get; set; } 

    [DisplayName("Bank Account Type")] 
    [Required] 
    public AccountTypeEnum AccountType { get; set; } 

    [DisplayName("Name on Bank Account")] 
    [Required(ErrorMessage = "You must provide the name on your bank account")] 
    public String AccountName { get; set; } 
} 

teraz, w naszej ViewModel mamy wyboru związanego z naszym DepositRequired boolean i EditorFor w/niestandardowy szablon dla BankInfo. Po złożeniu wniosku mamy kłopot z ustaleniem, w jaki sposób wyłączyć sprawdzanie poprawności na BankInfo IF nie jest wymagane przez model (np. Nawet jeśli nie wymagamy właściwości w ViewModel, to nadal wyzwala ona wartość Val w BankInfo i dlatego nie działa żałośnie w dowolnej formie). Czy istnieje jakiś standardowy sposób radzenia sobie z walidacją modelu zagnieżdżonego w powiązaniu ViewModel?

+0

jako notatkę, nawet jeśli mamy zgrać nasz własny walidator off BankInfo i pozostawić ją jako własność undecorated na ViewModel, walidacja BankInfo nadal w rzutach nawet jeśli ISN własności” t jest związany z przesłaniem formularza. – antinescience

+0

Powodem, dla którego sprawdza się walidacja BankInfo, jest to, że domyślny segregator modelu będzie całkowicie wiązał i sprawdzał dzieci potomne modelu, zanim będzie mógł zakończyć wiązanie i sprawdzić poprawność samego modelu kontenera. Nie jestem pewien, czy istnieje sposób obejścia tego poza tworzeniem niestandardowego spoiwa modelu. – rossisdead

Odpowiedz

5

Niestety, za pomocą wbudowanego w walidacji, trzeba by użyć

ModelState.Remove("BankInfo"); 

warunkowo ignorować wszelkie błędy sprawdzania poprawności na temat tego obiektu.

przypadku korzystania FluentValidation jest opcją, można zrobić coś takiego w swoim OurViewModelValidator:

RuleFor(ourViewModel=> ourViewModel.BankInfo).SetValidator(new BankInfoValidator()).When(ourViewModel=> ourViewModel.DepositRequired); 

i pozwól walidacji uchwyt BankInfoValidator tego obiektu.

Coś jak:

public class BankInfoValidator : AbstractValidator<BankInfo> 
{ 
    public BankAccountInfoValidator() 
    { 
     RuleFor(bank => bank.AccountName).NotEmpty().WithMessage("You must provide a name for your bank account."); 
     RuleFor(bank => bank.AccountNumber).NotEmpty().WithMessage("You must provide an account number for your bank information."); 
     RuleFor(bank => bank.AccountType).NotEmpty().WithMessage("You must select what kind of bank account you're entering information for (checking, savings)."); 
     RuleFor(bank => bank.ABANumber).NotEmpty().WithMessage("You must provide a routing number for your bank information."); 
     RuleFor(bank => bank.ABANumber).Must(BeOnlyDigits).WithMessage("Your routing number can only contain numeric characters, 0-9."); 
     RuleFor(bank => bank.AccountNumber).Must(BeOnlyDigits).WithMessage("Your account number can only contain numeric characters, 0-9."); 
    } 

    private bool BeOnlyDigits(string digitString) 
    { 
     int result; 
     return int.TryParse(digitString, out result); 
    } 
+0

+1 dla [FluentValidation] (http://fluentvalidation.codeplex.com/) - znalazłem go z wielu innych pobieżnych spojrzeń na posty SO i to * niesamowite * jak dotąd. Ogromne podziękowania dla Jeremy'ego Skinnera za pracę nad nim. – antinescience