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;
}
}
}
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;
}
}
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; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With