How would I go about having multiple textboxes on an MVC 3 form treated as one for the purposes of validation?
It\'s a simple phone number field with one textbox for
Scott, Is using a custom model binder within your scope? If so, you can implement an IModelBinder to combine the results from the three text fields into a single phone number field, which can be decorated with validation attributes. Here's a stackoverflow question that has an example of how to do this: DataAnnotation Validations and Custom ModelBinder
You could handle this by putting IValidatableObject
on the model class, and implementing the Validate
method.
It could look something like this:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (String.IsNullOrEmpty(_PhonePart1) || String.IsNullOrEmpty(_PhonePart2)
|| String.IsNullOrEmpty(_PhonePart3))
{
yield return new ValidationResult("You must enter all " +
"three parts of the number.");
}
}
I actually ended up implementing a custom ValidationAttribute
to solve this, using the same type of logic presented in CompareAttribute
that allows you to use reflection to evaluate the values of other properties. This allowed me to implement this at the property level instead of the model level and also allows for client side validation via unobtrusive javascript:
public class MultiFieldRequiredAttribute : ValidationAttribute, IClientValidatable
{
private readonly string[] _fields;
public MultiFieldRequiredAttribute(string[] fields)
{
_fields = fields;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
foreach (string field in _fields)
{
PropertyInfo property = validationContext.ObjectType.GetProperty(field);
if (property == null)
return new ValidationResult(string.Format("Property '{0}' is undefined.", field));
var fieldValue = property.GetValue(validationContext.ObjectInstance, null);
if (fieldValue == null || String.IsNullOrEmpty(fieldValue.ToString()))
return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
}
return null;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "multifield"
};
}
}