Передать переменные данные в ValidationAttribute

У меня есть требование применять разные значения минимальной длины в функции смены пароля к новому паролю, создаваемому на основе ролей пользователя. Если у пользователя нет административных ролей, минимальная длина составляет 12, если у них есть роли администратора, минимальная длина составляет 16.

Текущий код не имеет такой логики требований к переменным. Реализация нового свойства пароля была такой же в классе модели с именем ChangePasswordData:

    ///summary>
    /// Gets and sets the new Password.
    /// </summary>
    [Display(Order = 3, Name = "NewPasswordLabel", ResourceType = typeof(UserResources))]
    [Required]
    [PasswordSpecialChar]
    [PasswordMinLower]
    [PasswordMinUpper]
    [PasswordMaxLength]
    [PasswordMinLength]
    [PasswordMinNumber]
    public string NewPassword { get; set; }

Атрибут проверки устанавливается следующим образом:

/// <summary>
/// Validates Password meets minimum length.
/// </summary>
public class PasswordMinLength : ValidationAttribute
{
    public int MinLength { get; set; }

    public bool IsAdmin { get; set; }

    public PasswordMinLength()
    {
        // Set this here so we override the default from the Framework
        this.ErrorMessage = ValidationErrorResources.ValidationErrorBadPasswordLength;

        //Set the default Min Length
        this.MinLength = 12;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null || !(value is string) || !UserRules.PasswordMinLengthRule(value.ToString(), this.MinLength))
        {
            return new ValidationResult(this.ErrorMessageString, new string[] { validationContext.MemberName });
        }

        return ValidationResult.Success;
    }
}

Я хочу иметь возможность установить значение MinLength на 12 или 16 в зависимости от значения IsAdmin, однако я не могу понять, как украсить атрибут [PasswordMinLength(IsAdmin=myvarable)]. Допускаются только константы. Как я могу ввести значение свойства в ValidationAttribute, которое я могу оценить, чтобы определить правильную минимальную длину?

Спасибо!


person djcohen66    schedule 16.08.2016    source источник
comment
Я не думаю, что то, чего вы хотите достичь, возможно, потому что в значении атрибута разрешены только статические константы.   -  person DevilSuichiro    schedule 16.08.2016
comment
Я понимаю, что не могу просто украсить атрибут значением переменной, но есть ли способ ввести значения в коллекцию элементов контекста проверки или какой-либо другой метод, чтобы внутри IsValid я мог что-то оценить, чтобы узнать, что у рассматриваемого пользователя есть роли администратора?   -  person djcohen66    schedule 16.08.2016
comment
Один из вариантов — просто использовать проверка на уровне класса в вашей модели представления. В противном случае вы сможете создать аннотацию, например [PasswordMinLength(IsAdmin)], а затем получить доступ к этому свойству при проверке, используя метод, аналогичный этому: odetocode.com/blogs/scott/archive/2011/02/21/   -  person Steve Greene    schedule 16.08.2016
comment
Отличная ссылка! Я постараюсь обработать это, спасибо!   -  person djcohen66    schedule 17.08.2016


Ответы (1)


Спасибо Стиву Грину за ссылку на пример (http://odetocode.com/blogs/scott/archive/2011/02/21/custom-data-annotation-validator-part-i-server).-code.aspx), у меня есть ответ на мой проверочный вопрос. Вот обновленный код:

/// <summary>
/// Validates Password meets minimum length.
/// </summary>
public class PasswordMinLength : ValidationAttribute
{
    public int MinLength { get; set; }

    public PasswordMinLength(string IsAdminName)
    {
        // Set this here so we override the default from the Framework
        this.ErrorMessage = ValidationErrorResources.ValidationErrorBadPasswordLength;
        IsAdminPropertyName = IsAdminName;
        //Set the default Min Length
        this.MinLength = 12;
    }

    public string IsAdminPropertyName{ get; set; }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(ErrorMessageString, name, IsAdminPropertyName);
    }

    protected bool? GetIsAdmin(ValidationContext validationContext)
    {
        var retVal = false;
        var propertyInfo = validationContext
                              .ObjectType
                              .GetProperty(IsAdminPropertyName);
        if (propertyInfo != null)
        {
            var adminValue = propertyInfo.GetValue(
                validationContext.ObjectInstance, null);

            return adminValue as bool?;
        }
        return retVal;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (GetIsAdmin(validationContext) != null)
        {
            if (GetIsAdmin(validationContext) == true)
                this.MinLength = 16;
            else
                this.MinLength = 12;
        }
        else
            this.MinLength = 12;

        if (value == null || !(value is string) || !UserRules.PasswordMinLengthRule(value.ToString(), this.MinLength))
        {
            return new ValidationResult(this.ErrorMessageString, new string[] { validationContext.MemberName });
        }

        return ValidationResult.Success;
    }

}

Я просто добавил свойство IsAdmin в свой класс Model и украсил атрибут PasswordMinLength следующим образом:

[Display(Order = 3, Name = "NewPasswordLabel", ResourceType = typeof(UserResources))]
[Required]
[PasswordSpecialChar]
[PasswordMinLower]
[PasswordMinUpper]
[PasswordMaxLength]
[PasswordMinLength("IsAdmin")]
[PasswordMinNumber]
public string NewPassword { get; set; }

public bool IsAdmin { get; set; }

Работает как шарм. Спасибо, Стив!

person djcohen66    schedule 17.08.2016