Bri*_*ord 3 asp.net-mvc fluentvalidation data-annotations
我使用 FluentValidation 框架向 MVC 项目中的模型添加验证和注释。
我需要将数据注释添加到模型的类级别。即,模型需要添加 DisplayColumn 属性。但是,由于我使用 FluentValidation(并且将应用程序的 ModelMetadataProvider 设置为使用 FluentValidation),即使我将 DisplayColumn 属性放在模型类上,它也不会被使用。但是,我找不到使用 FluentValidation 添加该注释的方法。
有谁知道我如何让它发挥作用?
谢谢
我实际上不推荐使用 FluentValidationModelMetadataProvider - 这只是一个实验性的添加(很可能会从下一个版本中删除),并且它不支持任何类级别的 DataAnnotations(例如 DisplayColumn)。我建议您仅将 FluentValidation 用于验证,但坚持使用元数据的属性。
话虽如此,如果您真的想让它工作,那么您可以通过使用仅用于元数据的自定义无操作验证器来实现:
public static class MetadataExt {
public static IRuleBuilderOptions<T, TProperty> DisplayColumn<T, TProperty>(this IRuleBuilder<T, TProperty> rule) {
var ruleBuilder = (FluentValidation.Internal.RuleBuilder<T, TProperty>)rule;
ruleBuilder.Rule.AddValidator(new DisplayColumnWrapper(ruleBuilder.Rule.PropertyName));
return ruleBuilder;
}
public class DisplayColumnWrapper : NoopPropertyValidator, IAttributeMetadataValidator {
private string name;
public DisplayColumnWrapper(string name) {
this.name = name;
}
public override IEnumerable<ValidationFailure> Validate(PropertyValidatorContext context) {
return Enumerable.Empty<ValidationFailure>();
}
public Attribute ToAttribute() {
return new DisplayColumnAttribute(name);
}
}
}
Run Code Online (Sandbox Code Playgroud)
...然后你可以这样使用:
public class Validator : AbstractValidator<SomeModel> {
public Validator() {
RuleFor(x => x.DisplayColumnProperty)
.DisplayColumn();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您需要创建一个自定义 ModelMetadataProvider 来了解如何处理:
public class ExtendedFVModelMetadataProvider : FluentValidationModelMetadataProvider {
IValidatorFactory _validatorFactory;
public ExtendedFVModelMetadataProvider(IValidatorFactory validatorFactory)
: base(validatorFactory) {
this._validatorFactory = validatorFactory;
}
public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType) {
var validator = _validatorFactory.GetValidator(modelType);
if (validator == null) {
return base.GetMetadataForType(modelAccessor, modelType);
}
// Only look for the DisplayColumnWrapper
// There is a mismatch as MVC expects this to be defined at class-level, but FV defines everything at the property level.
var displayColumns = from memberWithValidator in validator.CreateDescriptor().GetMembersWithValidators()
from propertyValidator in memberWithValidator
let wrapper = propertyValidator as MetadataExt.DisplayColumnWrapper
where wrapper != null
select wrapper.ToAttribute();
var displayColumn = displayColumns.FirstOrDefault();
// we found a displaycolumn, so pass it over to MVC to build the metadata.
if (displayColumn != null) {
return CreateMetadata(new[] { displayColumn }, null /* containerType */, modelAccessor, modelType, null /* propertyName */);
}
return base.GetMetadataForType(modelAccessor, modelType);
}
}
Run Code Online (Sandbox Code Playgroud)
提供程序覆盖 GetMetadataForModel 方法并查找使用 DisplayColumn 的任何属性。如果您也想支持任何其他自定义元数据扩展,这可能会被扩展。然后,您可以使用此提供程序代替 FluentValidation 附带的元数据提供程序。
但是,我仍然不推荐这种方法……该库旨在执行验证,而不是用于生成 UI 元数据。
| 归档时间: |
|
| 查看次数: |
2491 次 |
| 最近记录: |