FluentValidation

时间:2015-04-28 07:24:07

标签: c# asp.net-mvc asp.net-mvc-4 unobtrusive-validation fluentvalidation

我在Asp.Net MVC 4应用程序中使用FluentValidation。我已经知道一些规则会自动为jQuery验证库生成属性。此脚本库已经知道必须检查的内容,例如data-rule-requireddata-rule-range等等。

我知道FluentValidation中有一些功能,但客户端不包含这些功能。例如:.Equal(true)。 我已经检查了@DarinDimitrov回复here,并且没有任何问题地实现了这一点。

但是,我不想总是创建从FluentValidationPropertyValidator继承的新类。我们必须将此添加到global.asax中的提供者:

provider.Add(typeof(EqualValidator), (metadata, context, description, validator) => new EqualToValueClientRule(metadata, context, description, validator));

在这种情况下,EqualValidator已在FluentValidation中实现。但是,如果我们使用When关键字创建了验证器,该怎么办?例如,我有:

this.RuleFor(phone => phone.Digits)
    .Length(7)
        .When(phone => phone.PrefixId == 2)
        .WithMessage("Numbers in 2nd city must contain 7 characters");

this.RuleFor(phone => phone.Digits)
    .Length(7)
        .When(phone => phone.PrefixId > 64)
        .WithMessage("Mobile number must contain 7 characters");

this.RuleFor(phone => phone.Digits)
    .Length(5)
        .When(phone => phone.PrefixId != 2)
        .WithMessage("Numbers in other cities must contain 5 characters")

当然,我可以使用jQuery / JavaScript检查这一点,没有任何问题。但是,这种方法并不好。在其他情况下,您必须编写如此多的代码以在客户端生成自定义属性并向适配器添加新功能。或者,只使用jQuery / JavaScript?还是其他任何东西?我们可以将JavaScript函数名称添加到FluentValidationPropertyValidator吗?

你推荐我什么?

1 个答案:

答案 0 :(得分:3)

我已经考虑了很多,并且发现最好的方法是创建一个继承自PropertyValidator并实现IClientValidatable接口的新验证器。因此,它将包含服务器端验证,并将根据需要生成不显眼的属性。然后我们必须在不显眼的库中注册这个新的验证器。

例如,我问题中规则的验证器将是:

public class MustFitToPhonePrefix<TModel, TProperty> : PropertyValidator, IClientValidatable
    {
        private string dependencyElement;

        public MustFitToPhonePrefix(Expression<Func<TModel, TProperty>> expression)
            : base("Format is wrong")
        {
            dependencyElement = (expression.Body as MemberExpression).Member.Name;
        }

        // Server side validation
        protected override bool IsValid(PropertyValidatorContext context)
        {
            // Instance of the class which contains property which must be validated 
            var phone = context.ParentContext.InstanceToValidate as PhoneDetail;

            ...
            // Custom logic
            ...

            // Everything is valid
            return true;
        }

        // Generate jquery unobtrusive attributes
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = this.ErrorMessageSource.GetString(), // default error message
                ValidationType = "fittoprefix" // name of the validatoin which will be used inside unobtrusive library
            };

            rule.ValidationParameters["prefixelement"] = dependencyElement; // html element which includes prefix information
            yield return rule;
        }

现在我们可以注册我们的客户端验证器:

// Will check if the phone number fits to phone prefix
$.validator.addMethod('fittoprefix', function (value, element, params) {
    var parent = getParentPropertyName(element);
    var prefixId = $("#{0}_{1}".format(parent, params.prefixelement)).val();
    var digitsLength = $(element).val().Length;

    ...
    // Custom logic
    ...

    return true;
});

// Registration - Will check if the phone number fits to phone prefix
$.validator.unobtrusive.adapters.add('fittoprefix', ['prefixelement'], function (options) {
    options.rules['fittoprefix'] = options.params;
    if (options.message != null) {
        options.messages['fittoprefix'] = options.message;
    }
});

最后,我们可以设置验证器:

   this.RuleFor(m => m.Digits)
       .SetValidator(new MustFitToPhonePrefix<PhoneDetail, int>(m => m.PrefixId));