IsValid evaluates a model property's value when the validation framework processes its ValidationAttribute. It receives the value and a ValidationContext, then returns success or a ValidationResult. section 32.3
A custom IsValid implementation can:
- Cast the supplied value, compare it with allowed values, and return an error for invalid input. section 32.3
- Read ValidationContext.ObjectInstance when validity depends on another property, enabling model-level comparisons. section 32.3
- Access a service through the context when validation requires externally provided values. section 32.3
Validating currency codes
A CurrencyCodeAttribute accepts allowed codes such as GBP, USD, CAD, and EUR. If a submitted value such as £$% is invalid, IsValid returns a ValidationResult, ModelState becomes invalid, and the application receives the message “Not a valid currency code.” section 32.3
Listing 32.8 Custom validation attribute for currency codes
public class CurrencyCodeAttribute : ValidationAttribute #1 { private readonly string[] _allowedCodes; #2 public CurrencyCodeAttribute(params string[] allowedCodes) #2 { #2 _allowedCodes = allowedCodes; #2 } #2 protected override ValidationResult IsValid( #3 object value, ValidationContext context) #3 { if(value is not string code #4 || !_allowedCodes.Contains(code)) #5 { #5 return new ValidationResult("Not a valid currency code"); #5 } return ValidationResult.Success; #6 } } #1 Derives from ValidationAttribute to ensure that your attribute is used during validation #2 The attribute takes in an array of allowed currency codes. #3 The IsValid method is passed the value to validate and a context object. #4 Tries to cast the value to a string and store it in the code variable #5 If the value provided isn’t a string, is null, or isn’t an allowed code, returns an error . . . #6 . . .otherwise, returns a success result.
Inspect the complete CurrencyCodeAttribute shape, including its allowed-code constructor and IsValid override. section 32.3
