I am having trouble performing data type validation which is dependent on another field. Most of the examples I found here are for making a field required or not based on a value of another field (MaidenName
will be required only if IsMarried
is true
).
My Model
public class AttributeValuesModel
{
public IList<AttributeModel> Values {get; set;}
}
public class AttributeModel
{
[Required]
public string AttributeName {get; set;}
[Required]
public string AttributeValue {get; set;}
[Required]
public int DataTypeId {get; set;}
}
What I would like to do is to validate the user input for AttributeValue based on the value of DataTypeId. For clarity, the value of DataTypeId
is known before I even show the view to the user.
//Possible values for DataTypeId are
//1 for decimal
//2 for dates
//3 for integer
Is this possible?
It's not so hard to roll your own validation attribute. I have implemented one some time ago. It checks whether value of other property is smaller than property that is decorated with this attribiute:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited=true)]
public class SmallerThanAttribute : ValidationAttribute
{
public SmallerThanAttribute(string otherPropertyName)
{
this.OtherPropertyName = otherPropertyName;
}
public string OtherPropertyName { get; set; }
public string OtherPropertyDisplayName { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
return IsValid(OtherPropertyName, value, validationContext);
}
private ValidationResult IsValid(string otherProperty, object value, ValidationContext validationContext)
{
PropertyInfo otherPropertyInfo = validationContext.ObjectType.GetProperty(otherProperty);
if (otherPropertyInfo == null)
{
throw new Exception("Could not find property: " + otherProperty);
}
var displayAttribute = otherPropertyInfo.GetCustomAttributes(typeof(DisplayAttribute), true).FirstOrDefault() as DisplayAttribute;
if (displayAttribute != null && OtherPropertyDisplayName == null)
{
OtherPropertyDisplayName = displayAttribute.GetName();
}
object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
var smaller = (IComparable) value;
var bigger = (IComparable) otherPropertyValue;
if (smaller == null || bigger == null)
{
return null;
}
if (smaller.CompareTo(bigger) > 0)
{
return new ValidationResult(string.Format(ValidatorResource.SmallerThan, validationContext.DisplayName, OtherPropertyDisplayName));
}
return null;
}
}
There is one gotcha. Error message format is defined in resource class property (ValidatorResource.SmallerThan), so it's not pluggable -- I didn't need this. However, I think it still could be a good starting point for you.