Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC Form Validation on Multiple Fields

Tags:

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 area code, one for prefix and one for the last four digits.

There are really two validation requirements:

1) They're all required. 2) They must all contain integers.

Now this is simple when doing it for individual fields but how can I create the equivalent of an ASP.NET CustomValidator with MVC so that I can validate all three fields as a whole?

like image 888
Scott Avatar asked May 20 '11 17:05

Scott


2 Answers

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"
            };
        }
    }
like image 60
Scott Avatar answered Oct 11 '22 21:10

Scott


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.");
      }

}
like image 30
awright Avatar answered Oct 11 '22 19:10

awright