ASP.NET MVC - Pass model value to data annotation parameter

南楼画角 提交于 2019-12-07 08:47:30

问题


I want to pass a value from one of my properties in my model to my data annotation to validate my password property, but I have no idea how I can achieve this. When I am doing this at this way I get the following error:

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

My model:

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

And in my data annotation I am doing this:

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

回答1:


You can't pass variable values (values that are not evaluated at compile-time) into attributes. They have to be literal values or constant values.

What you can pass into attributes, though, are the names of the properties of your model that you want to evaluate at run-time, and then have your IsValid method evaluate these values at run-time by accessing the ValidationContext in the override that returns a ValidationResult of ValidationAttribute.

Or, if you are always evaluating these same properties, then you can just grab the reference to your model, and use that directly:

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



回答2:


It's not possible, because the attributes, including their data, are placed into the metadata of the assembly at compile-time. See Attribute parameter types on MSDN.

Instead you can pass a name of the dependent property as a string. I will show you a sample with one property and you will add others the same way:

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

       ...
    }
}

Then

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



回答3:


As far as I know, you can't pass the variable values into attributes. You could add custom validation rule to your model:

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

You could also change it into multiple if statements and add seperate ValidationResults (one for Voornaam, one for Achternaam and one for Gebruikersnaam).



来源:https://stackoverflow.com/questions/21680554/asp-net-mvc-pass-model-value-to-data-annotation-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!