2013-05-03 60 views
2

我使用Foolproof Validation,所以我可以在我的視圖模型上使用[RequiredIf]屬性。問題是我想在代碼中使用控制器外部的相同邏輯觸發驗證。手動觸發萬無一失的驗證

我試着創建我自己的驗證上下文,並使用Validatior.TryValidateObject;然而,它與Foolproof的自定義RequiredIf驗證器失敗。有沒有辦法讓我的模型和驗證它,而不是傳遞給控制器​​?

我使用了錯誤的方法嗎?

這裏是我的代碼:

var draftModel = _draftHelper.LoadDraft(draftId); 

var validationResults = new List<ValidationResult>(); 

var vc = new ValidationContext(draftModel, null, null); 

var isValidDraft = Validator.TryValidateObject(draftModel, vc, 
               validationResults, true); 

而且我的錯誤是在TryValidateObject線

System.NotImplementedException:該方法或操作未實現 。

回答

3

我認爲一個更好的方法是使用FluentValidation,而不是萬無一失的驗證。我個人認爲Fluent比屬性更好:)。

使用FluentValidation,您也可以在不使用控制器的情況下驗證模型。

DraftVM draft = draftRepository.Get(draftId); 

var DraftValidator validator = new DraftVMValidator(); 
ValidationResult results = validator.Validate(draft); 

public class DraftVMValidator : AbstractValidator<DraftViewModel> 
{ 
     public DraftVMValidator() 
     { 

     RuleFor(vm => vm.OptionalField) 
      .Must(BeFilledIfNameNotEmpty) 
      .WithMessage("Optional Field required because you filled out Name field"); 
     } 


     public bool BeFilledIfNameNotEmpty(DraftVM viewModel) 
     { 
      return !string.IsNullOrWhiteSpace(viewModel.Name); 
     } 

} 

這不會給你一個System.NotImplemented異常。

此驗證程序是乾的,因爲您也可以將其插入ASP.NET MVC驗證。
您可以簡單地在Global.asax或App_Start等中調用以下代碼。所有驗證器都將其綁定到MVC Model Validation,或將其用於任何常規應用程序。

FluentValidationModelValidatorProvider.Configure(); // This will bind it for you 

如果您使用Ninject的Inversion of Control容器,FluentValidation也有一個插件可以使用它。在上面提供的鏈接中提供了更多的文檔。

如果您想查看更多此Validator代替FoolProof的示例,我在Github中有一個相當大的項目示例。 Example Validators with ASP.NET MVC 4

+0

感謝@Patrick馬吉,這可能是正確的做法。我還沒有意識到Fluent也支持客戶端驗證。我會在今天測試它,如果它還提供自定義客戶端驗證,那麼這將是我的答案。 – 2013-05-13 16:52:42

+0

您也可以使用REMOTE驗證來使用FluentValidation,例如電子郵件,這些電子郵件需要使用Ajax進行唯一驗證,而無需用戶回發表單。我的項目中也有一個例子。由於Predicate(Must)函數默認不支持遠程驗證。你可以創建自定義活頁夾。 – 2013-05-13 17:01:04

+0

感謝@Patrick Magee,我測試了您的解決方案並且效果很好。這解決了我的問題。至於[遠程],將工作;不過,如果可能的話,我仍然更喜歡客戶端自定義驗證器。 – 2013-05-14 23:03:21

2

你需要讓MVC框架提供的,而不是使用Validator.TryValidateObject如下您的驗證:

var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => viewModelToValidate, viewModelToValidate.GetType()); 
var compositeValidator = ModelValidator.GetModelValidator(modelMetadata, controller.ControllerContext); 
foreach (ModelValidationResult result in compositeValidator.Validate(null)) 
{ 
    validationResults.Add(new ValidationResult(result.Message, new List<string> { result.MemberName })); 
}