我正在使用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:方法或操作不是 实现。
答案 0 :(得分:3)
我认为更好的方法是使用FluentValidation,而不是万无一失的验证。我个人认为Fluent比属性更好:)。
使用FluentValidation,您还可以在不使用Controller的情况下验证模型。
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也有一个插件可以使用它。有关其文档的更多信息,请参见上面提供的链接。
如果你想看到这个Validator的更多例子而不是FoolProof,我在我的Github中有一个非常大的项目示例。 Example Validators with ASP.NET MVC 4
答案 1 :(得分:2)
您需要让MVC框架提供您的Validator,而不是使用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 }));
}