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

4

我希望能够从我的模型属性中传递一个值给我的数据注释,以验证我的密码属性。但是我不知道如何实现这一点。当我按照这种方式进行操作时,会出现以下错误:

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个回答

9

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

但是,您可以将要在运行时评估的模型属性名称传递到属性中,并通过访问重写中的 ValidationContext 让您的 IsValid 方法在运行时评估这些值,返回一个 ValidationAttributeValidationResult

或者,如果您始终评估相同的属性,则可以直接获取对模型的引用并直接使用:

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
这对我来说很好用,只需要做一些小的调整,谢谢! - Jamie
为什么你返回布尔值而不是“ValidationResult”? - muttley91

5

这是不可能的,因为属性及其数据在编译时被放置到程序集的元数据中。请参见MSDN上的属性参数类型

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

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; }

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)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接