2013-05-03 58 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 })); 
}