Проверка на стороне клиента для пользовательского атрибута ValidationAttribute с AttributeTargets.Class - PullRequest
4 голосов
/ 27 апреля 2011

Возможно ли реализовать проверку клиентского сайта для пользовательского атрибута ValidationAttribute, который используется в области видимости класса? Например, мой MaxLengthGlobal, который должен обеспечить глобальный максимальный предел для всех полей ввода.

[AttributeUsage(AttributeTargets.Class)]
public class MaxLengthGlobalAttribute : ValidationAttribute, IClientValidatable
{
    public int MaximumLength
    {
        get;
        private set;
    }

    public MaxLengthGlobalAttribute(int maximumLength)
    {
        this.MaximumLength = maximumLength;
    }

    public override bool IsValid(object value)
    {
        var properties = TypeDescriptor.GetProperties(value);

        foreach (PropertyDescriptor property in properties)
        {
            var stringValue = property.GetValue(value) as string;

            if (stringValue != null && (stringValue.Length > this.MaximumLength))
            {
                return false;
            }
        }

        return true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {       
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = this.FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "maxlengthglobal",
        };

        rule.ValidationParameters.Add("maxlength", this.MaximumLength);         
        yield return rule;
    }
}

Спасибо.

Ответы [ 2 ]

5 голосов
/ 19 августа 2011

Я нашел этот ответ, когда искал решение той же проблемы, и предложил обходной путь.

Вместо 1 ValidationAttribute, имейте 2:

1.) ServerValidationAttribute будетбыть в классе, и не будет реализовывать IClientValidatable.

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class MyCustomServerValidationAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        // remember to cast to the class type, not property type
        // ... return true or false
    }
}

2.) Атрибут ClientValidationAttribute будет находиться в поле / свойстве и будет реализовывать IClientValidatable, но переопределение IsValid всегда возвращает true.

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, 
    AllowMultiple = false, Inherited = true)]
public class MyCustomClientValidationAttribute : ValidationAttribute, 
    IClientValidatable
{
    public override bool IsValid(object value)
    {
        return true;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
        ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = ErrorMessage,
            ValidationType = "mycustomvalidator",
        };

        var viewContext = (ViewContext)context;
        var dependentProperty1 = viewContext.ViewData.TemplateInfo
            .GetFullHtmlFieldId("DependentProperty1");
        //var prefix = viewContext.ViewData.TemplateInfo.HtmlFieldPrefix;

        rule.ValidationParameters.Add("dependentproperty1", dependentProperty1);

        yield return rule;
    }
}

При выполнении на клиентеатрибут сервера игнорируется, и наоборот.

Если вам необходимо иметь атрибут проверки в классе, скорее всего, проверка происходит по нескольким полям.Я добавил некоторый шаблонный код для передачи дополнительных параметров методу проверки клиента, но он работает не так, как я ожидал.В моем собственном коде я закомментировал переменные viewContext и independentProperty1 и просто передал строку «DependentProperty1» во второй аргумент метода rule.ValidationParameters.Add.По какой-то причине я получаю неправильный HtmlFieldPrefix.Если кто-то может помочь с этим, пожалуйста, прокомментируйте ...

В любом случае, вы получите такую ​​модель представления:

[MyCustomServerValidation(ErrorMessage = MyCustomValidationMessage)]
public class MyCustomViewModel
{
    private const string MyCustomValidationMessage = "user error!";

    [Display(Name = "Email Address")]
    [MyCustomClientValidation(ErrorMessage = MyCustomValidationMessage)]
    public string Value { get; set; }

    [HiddenInput(DisplayValue = false)]
    public string DependentProperty1 { get; set; }
}

Клиентский скрипт, подобный этому:

/// <reference path="jquery-1.6.2.js" />
/// <reference path="jquery.validate.js" />
/// <reference path="jquery.validate.unobtrusive.js" />

$.validator.addMethod('mycustomvalidator', function (value, element, parameters) {
    var dependentProperty1 = $('#' + parameters['dependentproperty1']).val();
    // return true or false
});
$.validator.unobtrusive.adapters.add('mycustomvalidator', ['dependentproperty1'], 
    function (options) {
        options.rules['mycustomvalidator'] = {
            dependentproperty1: options.params['dependentproperty1']
        };
        options.messages['mycustomvalidator'] = options.message;
    }
);

И такой вид:

@Html.EditorFor(m => m.Value)
@Html.EditorFor(m => m.DependentProperty1)
@Html.ValidationMessageFor(m => m.Value)
@Html.ValidationMessageFor(m => m)

Тогда, если у вас отключена проверка клиента, вместо значения для свойства отображается @Html.ValidationMessageFor(m => m).

1 голос
/ 27 апреля 2011

Нет, это невозможно. К сожалению.

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