Передача ErrorMessage для проверки на стороне клиента - PullRequest
2 голосов
/ 11 апреля 2011

Поскольку нет способа проверить свойство (с помощью ненавязчивой проверки на стороне клиента) с использованием нескольких шаблонов регулярных выражений (поскольку тип проверки должен быть уникальным), я решил расширить FluentValidation, чтобы я мог сделать следующее.

RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required")
                    .Length(3, 20).WithMessage("Name must contain between 3 and 20 characters")
                    .Match(@"^[A-Z]").WithMessage("Name has to start with an uppercase letter")
                    .Match(@"^[a-zA-Z0-9_\-\.]*$").WithMessage("Name can only contain: a-z 0-9 _ - .")
                    .Match(@"[a-z0-9]$").WithMessage("Name has to end with a lowercase letter or digit")
                    .NotMatch(@"[_\-\.]{2,}").WithMessage("Name cannot contain consecutive non-alphanumeric characters");



Последнее, что мне нужно выяснить, это как передать сообщение об ошибке, которое устанавливается с помощью WithMessage() через GetClientValidationRules(), чтобы оно заканчивалось атрибутом «data-val-customregex [SOMEFANCYSTRINGHERETOMAKEITUNIQUE]» на элементе ввода.

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
    var rule = new ModelClientValidationRule();
    rule.ErrorMessage = [INSERT ERRORMESSAGE HERE];
    rule.ValidationType = "customregex" + StringFunctions.RandomLetters(6);
    rule.ValidationParameters.Add("pattern", pattern);

    yield return rule;
}


Я искал исходный код FluentValidation, но не смог понять это. У кого-нибудь есть идеи?

Ответы [ 2 ]

2 голосов
/ 12 апреля 2011

Я обсуждал, как это сделать с Джереми Скиннером (создателем Fluent Validation) вhttp://fluentvalidation.codeplex.com/discussions/253505

Он был достаточно любезен, чтобы написать полный пример.

Обновление Вот код, который мы придумали:

Сначала расширения для Match и NotMatch.

public static class Extensions
{
    public static IRuleBuilderOptions<T, string> Match<T>(this IRuleBuilder<T, string> ruleBuilder, string expression)
    {
        return ruleBuilder.SetValidator(new MatchValidator(expression));
    }

    public static IRuleBuilderOptions<T, string> NotMatch<T>(this IRuleBuilder<T, string> ruleBuilder, string expression) {
        return ruleBuilder.SetValidator(new MatchValidator(expression, false));
    }
}

Используемый интерфейс для валидатора

public interface IMatchValidator : IPropertyValidator
{
    string Expression { get; }
    bool MustMatch { get; }
}

Фактический валидатор:

public class MatchValidator : PropertyValidator, IMatchValidator
{
    string expression;
    bool mustMatch;

    public MatchValidator(string expression, bool mustMatch = true)
        : base(string.Format("The value {0} match with the given expression, while it {1}.", mustMatch ? "did not" : "did", mustMatch ? "should" : "should not"))
    {
        this.expression = expression;
        this.mustMatch = mustMatch;
    }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        return context.PropertyValue == null ||
               context.PropertyValue.ToString() == string.Empty ||
               Regex.IsMatch(context.PropertyValue.ToString(), expression) == mustMatch;
    }

    public string Expression
    {
        get { return expression; }
    }

    public bool MustMatch {
        get { return mustMatch; }
    }
}

Адаптер для регистрации валидатора:

public class MatchValidatorAdaptor : FluentValidationPropertyValidator
{
    public MatchValidatorAdaptor(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator)
        : base(metadata, controllerContext, rule, validator)
    {
    }

    IMatchValidator MatchValidator
    {
        get { return (IMatchValidator)Validator; }
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
        var formatter = new MessageFormatter().AppendPropertyName(Rule.PropertyDescription);
        string errorMessage = formatter.BuildMessage(Validator.ErrorMessageSource.GetString());
        yield return new ModelClientValidationMatchRule(MatchValidator.Expression, MatchValidator.MustMatch, errorMessage);
    }
}

И наконец, где происходит волшебство:

public class ModelClientValidationMatchRule : ModelClientValidationRule
{
    public ModelClientValidationMatchRule(string expression, bool mustMatch, string errorMessage)
    {
        if (mustMatch)
            base.ValidationType = "match";
        else
            base.ValidationType = "notmatch";

        base.ValidationType += StringFunctions.RandomLetters(6);
        base.ErrorMessage = errorMessage;
        base.ValidationParameters.Add("expression", expression);
    }
}

Обновление 2: Javascript для подключения jQuery.validator:

(function ($) {
    function attachMatchValidator(name, mustMatch) {
        $.validator.addMethod(name, function (val, element, expression) {
            var rg = new RegExp(expression, "gi");
            return (rg.test(val) == mustMatch);
        });

        $.validator.unobtrusive.adapters.addSingleVal(name, "expression");
    }

    $("input[type=text]").each(function () {
        $.each(this.attributes, function (i, attribute) {
            if (attribute.name.length == 20 && attribute.name.substring(0, 14) == "data-val-match")
                attachMatchValidator(attribute.name.substring(9, 20), true);

            if (attribute.name.length == 23 && attribute.name.substring(0, 17) == "data-val-notmatch")
                attachMatchValidator(attribute.name.substring(9, 23), false);
        });
    });
} (jQuery));
1 голос
/ 12 апреля 2011

Немного не по теме, но, возможно, полезно. Регулярные выражения довольно мощные, вы рассматривали возможность объединения всех правил в одном регулярном выражении? Я думаю, именно поэтому атрибуты, обеспечивающие проверку регулярных выражений, обычно не допускают нескольких экземпляров для каждого свойства.

Итак, для вашего примера, ваше регулярное выражение будет:

"^[A-Z]([a-zA-Z0-9][_\-\.]{0,1}[a-zA-Z0-9]*)*[a-z0-9]$"

И удобное место для проверки: http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...