C# FluentValidation中每个自定义规则的客户端验证的最佳方法

C# FluentValidation中每个自定义规则的客户端验证的最佳方法,c#,asp.net-mvc,asp.net-mvc-4,unobtrusive-validation,fluentvalidation,C#,Asp.net Mvc,Asp.net Mvc 4,Unobtrusive Validation,Fluentvalidation,我正在Asp.NETMVC4应用程序中使用FluentValidation。我已经知道一些规则会自动为jQuery验证库生成属性。这个脚本库已经知道它必须检查什么,例如在需要数据规则、数据规则范围等情况下 我知道FluentValidation中有一些函数,但这些函数不包括在客户端。例如:.Equal(true)。 我已经检查了答案,并且没有任何问题地实现了它 但是,我不希望总是创建从FluentValidationPropertyValidator继承的新类。我们必须像global.asax中

我正在Asp.NETMVC4应用程序中使用FluentValidation。我已经知道一些规则会自动为jQuery验证库生成属性。这个脚本库已经知道它必须检查什么,例如在
需要数据规则
数据规则范围
等情况下

我知道FluentValidation中有一些函数,但这些函数不包括在客户端。例如:
.Equal(true)
。 我已经检查了答案,并且没有任何问题地实现了它

但是,我不希望总是创建从
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


你推荐我什么?

我想了很多,发现最好的方法是创建新的验证器,该验证器继承自
PropertyValidator
,并实现
IClientValidable
接口。因此,它将包含服务器端验证,并按照我们的意愿生成不引人注目的属性。然后我们必须在不显眼的库中注册这个新的验证器

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

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));
this.RuleFor(m=>m.Digits)
.SetValidator(新MustFitToPhonePrefix(m=>m.PrefixId));

我认为最好的方法是创建PropertyValidator类,该类在服务器端始终有效,注册javascript函数名,该函数名将在客户端执行。@EvgenyLevin我已经做过了。此外,我的验证器还实现了
iclientvalidable
。它将在客户端创建验证属性。所以,我可以很容易地在其他项目中使用这个验证器。是的,你的验证器很好,可以作为电话验证器重用,但我的想法是创建“假”验证器,只在特殊属性中注册客户端函数,适配器,调用js函数,以及使用规则生成器链的扩展。然后调用将如下所示:
RuleFor(phone=>phone.Digits).Length(7.When(…).WithMessage(“…”).Length(5.When(…).WithMessage(“…”).ClientSideRule(“allPhoneValidationLogicWithWhenConditionsFunction”)@EvgenyLevin我知道了。但是,我将在哪里创建客户端属性?