1
\$\begingroup\$

This class validates that a name contains only letters and optionally spaces, hyphens and apostrophes.

public class NameAttribute : ValidationAttribute
{
 protected override ValidationResult IsValid(object value, ValidationContext validationContext)
 {
 if (value == null) return ValidationResult.Success;
 string name = value.ToString();
 var regex = new Regex(@"^[a-zA-Z]+(?:['-][a-zA-Z\s*]+)*$");
 return regex.IsMatch(name)
 ? ValidationResult.Success
 : new ValidationResult($"The name '{name}' is invalid, it should consist of only letters, and optionally spaces, apostrophes and/or hyphens.");
 }
}

One thing I wasn't sure on was the null check at the start, we've got the Required attribute if something is required and I don't want the validation to occur if the value is null. Is this an appropriate way of handling it?

asked Jun 25, 2020 at 11:10
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

From the separation of concerns perspective it seems fine that you do not want to validate against emptiness. On the other hand, one can argue that why do you treat an empty string as a valid name.

My suggestion is to create a ctor with a parameter, where the consumer of the attribute can define how should it behave in case of empty input.

public class NameAttribute : ValidationAttribute
{
 private static readonly Regex NameRegex = new Regex(@"^[a-zA-Z]+(?:['-][a-zA-Z\s*]+)*$", RegexOptions.Compiled);
 private readonly bool shouldTreatEmptyAsInvalid;
 public NameAttribute(bool shouldTreatEmptyAsInvalid = true)
 {
 this.shouldTreatEmptyAsInvalid = shouldTreatEmptyAsInvalid;
 }
 protected override ValidationResult IsValid(object value, ValidationContext validationContext)
 {
 if (value == null)
 return shouldTreatEmptyAsInvalid 
 ? new ValidationResult($"The name is invalid, it should not be empty.") 
 : ValidationResult.Success;
 return NameRegex.IsMatch(value.ToString())
 ? ValidationResult.Success
 : new ValidationResult($"The name '{value}' is invalid, it should consist of only letters, and optionally spaces, apostrophes and/or hyphens.");
 }
}

I moved the creation of the Regex to a static variable, but you should take some measurements in order to be sure, which has the best performance. Please check this MSDN article for other alternatives.

answered Jun 25, 2020 at 11:51
\$\endgroup\$
3
  • \$\begingroup\$ Thanks, so with that in mind, it would negate the need for a Required attribute, is that right? \$\endgroup\$ Commented Jun 25, 2020 at 12:25
  • \$\begingroup\$ @MF1010 With this version you are able to use this with / without the Required attribute. So your logic does not depend on the existence of an other attribute. \$\endgroup\$ Commented Jun 25, 2020 at 12:28
  • 1
    \$\begingroup\$ Thanks, that makes sense. \$\endgroup\$ Commented Jun 29, 2020 at 7:43

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.