Подтвердить что ты не робот

MVC 2 против MVC 3 пользовательских атрибутов проверки с использованием DataAnnotationsModelValidatorProvider.RegisterAdapter

Я читал на каком-то посту, но не могу найти его сейчас, когда в MVC 3 не было необходимости создавать Validator, а только атрибут. Это правда? Я действительно говорю, что я сбиваю с толку, что атрибут имеет IClientValidatable. Итак, что делает класс DataAnnotationsModelValidator, если аннотация содержит имя клиента script (IClientValidatable) и возможность проверки (ValidationAttribute IsValid)?

Было бы очень приятно, если бы мне не пришлось регистрировать атрибут с помощью Validator в глобальном. Это можно сделать? Я читал плохие советы?

EDIT: Интересно, что я просто протестировал его, исключив валидатор, поместив всю логику в IsValid, и он отлично работает. Я думаю, что единственное, что может отсутствовать, - это контекст контроллера, но я не уверен, что он полезен при проверке. У IsValid есть ValidationContext, у которого есть ServiceContainer, если мне нужна услуга. Какой-то реальный недостаток я здесь не собираюсь?

ИЗМЕНИТЬ 2: Я начну с валидатора из этого примера: http://blogs.msdn.com/b/simonince/archive/2010/06/04/conditional-validation-in-mvc.aspx

Атрибут:

public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
{
    private RequiredAttribute innerAttribute = new RequiredAttribute();
    public string DependentProperty { get; set; }
    public object TargetValue { get; set; }

    public RequiredIfAttribute(string dependentProperty, object targetValue)
    {
        this.DependentProperty = dependentProperty;
        this.TargetValue = targetValue;
    }

    public override bool IsValid(object value)
    {
        return innerAttribute.IsValid(value);
    }

    public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ModelClientValidationRule modelClientValidationRule = new ModelClientValidationRule()
        {
            ErrorMessage = FormatErrorMessage(metadata.DisplayName),
            ValidationType = "requiredifattribute"
        };
        modelClientValidationRule.ValidationParameters.Add("requiredifattribute", DependentProperty);
        yield return modelClientValidationRule;
    }
}

Валидатор:

public class RequiredIfValidator : DataAnnotationsModelValidator<RequiredIfAttribute>
{
    public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute)
        : base(metadata, context, attribute)
    {
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
        return base.GetClientValidationRules();
    }

    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
        var field = Metadata.ContainerType.GetProperty(Attribute.DependentProperty);
        if (field != null)
        {
            var value = field.GetValue(container, null);
            if ((value == null && Attribute.TargetValue == null) ||
                (value.Equals(Attribute.TargetValue)))
            {
                if (!Attribute.IsValid(Metadata.Model))
                    yield return new ModelValidationResult { Message = ErrorMessage };
            }
        }
    }
}

С текущим кодом выше, мне нужно зарегистрироваться в файле Global.asax.cs:

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute), typeof(RequiredIfValidator));

Но если я переведу все в только атрибут, мне не нужно его регистрировать:

public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
{
    private RequiredAttribute innerAttribute = new RequiredAttribute();
    public string DependentProperty { get; set; }
    public object TargetValue { get; set; }

    public RequiredIfAttribute(string dependentProperty, object targetValue)
    {
        this.DependentProperty = dependentProperty;
        this.TargetValue = targetValue;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var field = validationContext.ObjectInstance.GetType().GetProperty(DependentProperty);
        if (field != null)
        {
            var dependentValue = field.GetValue(validationContext.ObjectInstance, null);
            if ((dependentValue == null && TargetValue == null) ||
                (dependentValue.Equals(TargetValue)))
            {
                if (!innerAttribute.IsValid(value))
                    return new ValidationResult(ErrorMessage);
            }
        }
        return ValidationResult.Success;
    }

    public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ModelClientValidationRule modelClientValidationRule = new ModelClientValidationRule()
        {
            ErrorMessage = FormatErrorMessage(metadata.DisplayName),
            ValidationType = "requiredifattribute"
        };
        modelClientValidationRule.ValidationParameters.Add("requiredifattribute", DependentProperty);
        yield return modelClientValidationRule;
    }
}

Есть ли проблема с последним битом кода, заменяющим весь другой код? Почему я должен хранить класс валидатора?

4b9b3361

Ответ 1

CrazyDart,

Интерфейс IClientValidatable был добавлен в MVC3.

В вашем втором примере показано правильное использование этого нового интерфейса. Вы правы, что его не нужно регистрировать, и он предоставит необходимые правила на стороне клиента для проверки, а также проведет необходимую проверку на стороне сервера.

Идем дальше, наслаждайся.

counsellorben

Ответ 2

Когда я использую последний параметр из CrazyDart, серверная часть отлично работает в MVC4.

Кроме того, я не могу заставить проверку на стороне клиента работать. Он никогда не проверяет требуемое поле на стороне клиента (хотя есть несколько добавленных тегов).

Я также проверил 2-е сообщение в блоге (первое - это вдохновение плаката) Саймона Инса: http://blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in-asp-net-mvc-3.aspx