ASP.NET MVC - 将模型值传递给数据注释参数

时间:2014-02-10 15:01:39

标签: asp.net-mvc model data-annotations

我想从我的模型中的一个属性传递一个值到我的数据注释来验证我的密码属性,但我不知道如何实现这一点。当我这样做时,我得到以下错误:

an attribute argument must be a constant expression typeof expression or array

我的模特:

public class LoginModel
{
    public string Voornaam { get; set; }
    public string Achternaam { get; set; }
    public string Gebruikersnaam { get; set; }

    [Password(AttributeVoornaam = this.Voornaam, AttributeAchternaam = this.Achternaam, AttributeGebruikersnaam = this.Gebruikersnaam)]
    public string Wachtwoord { get; set; }
}

在我的数据注释中,我这样做:

public class PasswordAttribute : ValidationAttribute
{
    public string AttributeVoornaam { get; set; }
    public string AttributeAchternaam { get; set; }
    public string AttributeGebruikersnaam { get; set; }

    public override bool IsValid(object value)
    {
        string strValue = value.ToString();

        if (strValue.Contains(AttributeVoornaam.ToLower()) || strValue.Contains(AttributeAchternaam.ToLower()) ||
               strValue.Contains(AttributeGebruikersnaam.ToLower()))
        {
            ErrorMessage = "Uw wachtwoord mag niet uw voornaam, achternaam of gebruikersnaam bevatten.";
            return false;
        }
        else
        {
            return true;
        }
    }
}

3 个答案:

答案 0 :(得分:8)

您无法将变量值(在编译时未计算的值)传递到属性中。它们必须是字面值或常数值。

可以传递给属性的内容是您希望在运行时评估的模型属性的名称,然后使用IsValid方法评估这些属性通过访问覆盖中的ValidationContext来返回ValidationResult ValidationAttribute的运行时的值。

或者,如果您总是在评估这些相同的属性,那么您可以获取对模型的引用,并直接使用它:

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    LoginModel loginModel = (LoginModel)validationContext.ObjectInstance;

    string strValue = value.ToString();

    if (strValue.Contains(loginModel.Voornaam.ToLower()) || 
        strValue.Contains(loginModel.Achternaam.ToLower()) ||             
        strValue.Contains(loginModel.Gebruikersnaam.ToLower()))
    {
        ErrorMessage = "Uw wachtwoord mag niet uw voornaam, achternaam of gebruikersnaam bevatten.";
        return false;
    }
    else
    {
        return true;
    }
}

答案 1 :(得分:4)

这是不可能的,因为属性(包括其数据)在编译时被放入程序集的元数据中。请参阅MSDN上的Attribute parameter types

相反,您可以将依赖属性的名称作为字符串传递。我将向您展示一个带有一个属性的示例,您将以相同的方式添加其他属性:

public class PasswordAttribute : ValidationAttribute
{
    public PasswordAttribute(string voornaamPropertyName)
    {
        if(string.IsNullOrEmpty(voornaamPropertyName))
            throw new ArgumentNullException("voornaamPropertyName");

        VoornaamPropertyName = voornaamPropertyName;
    }

    public string VoornaamPropertyName { get; set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        PropertyInfo voornaamPropertyInfo = validationContext.ObjectType.GetProperty(VoornaamPropertyName);
        if (voornaamPropertyInfo == null)
        {
            return new ValidationResult(String.Format(CultureInfo.CurrentCulture, "Could not find a property named {0}", VoornaamPropertyName));
        }

        var voornaamProperty = voornaamPropertyInfo.GetValue(validationContext.ObjectInstance); // here you have the value of the property

       ...
    }
}

然后

[Password("Voornaam")]
public string Wachtwoord { get; set; }

答案 2 :(得分:1)

据我所知,您无法将变量值传递给属性。您可以将自定义验证规则添加到模型中:

public class LoginModel: IValidatableObject
{
    public string Voornaam {get;set;}
    public string Achternaam {get;set;}
    public string Gebruikersnaam {get;set;}

    public string Wachtwoord { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var results = new List<ValidationResult>();
        var pwd = this.Wachtwoord.ToLower();
        if(pwd.Contains(this.Voornaam.ToLower()) || pwd.Contains(this.Achternaam.ToLower()) || pwd.Contains(this.Gebruikersnaam.ToLower())){
            results.Add(new ValidationResult("Uw wachtwoord mag niet uw voornaam, achternaam of gebruikersnaam bevatten."));
        }
        return results;
    }
}

您还可以将其更改为多个if语句,并添加单独的ValidationResults(一个用于Voornaam,一个用于Achternaam,一个用于Gebruikersnaam)。