【问题标题】:Manually trigger foolproof validation手动触发万无一失的验证
【发布时间】:2013-05-03 00:44:14
【问题描述】:

我正在使用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:方法或操作不是 实施。

【问题讨论】:

    标签: asp.net-mvc foolproof-validation


    【解决方案1】:

    我认为更好的方法是使用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 异常。

    此验证器是 DRY,因为您也可以将其插入 ASP.NET MVC 验证中。
    您可以简单地在 Global.asax 或 App_Start 等中调用以下代码。一个验证器,将其绑定到 MVC 模型验证或在任何普通应用程序中使用。

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

    如果您使用像 Ninject 这样的 Inversion of Control 容器,FluentValidation 也有一个插件可以使用它。上面提供的链接中提供了有关其文档的更多信息。

    如果你想看到更多关于这个验证器而不是 FoolProof 的例子,我在我的 Github 中有一个非常大的项目例子。 Example Validators with ASP.NET MVC 4

    【讨论】:

    • 感谢@Patrick Magee,这可能是正确的方法。我没有意识到 Fluent 还支持客户端验证。我今天将对其进行测试,如果它还提供自定义客户端验证,那么这就是我的答案。
    • 您还可以使用远程验证来摆脱 FluentValidation,例如电子邮件需要使用 Ajax 进行验证,而无需用户回发表单。我的项目中也有一个例子。由于 Predicate (Must) 函数默认不支持远程验证。不过,您可以创建自定义活页夹。
    • 感谢@Patrick Magee,我测试了您的解决方案,效果很好。这解决了我的问题。至于 [Remote] 会起作用的;但是,如果可能的话,我仍然更喜欢客户端自定义验证器。
    【解决方案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 }));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-21
      • 2020-02-29
      • 2020-05-27
      相关资源
      最近更新 更多