Introduction
In this second article, we will learn all validation forms in DataAnnotation. We will review Validator class with all its structure. The first part can be found on the following link.
DataAnnotation enables us to work with positive programming. In other words, it allows us anticipate exceptions for problems in our business classes or domain classes. It provides better performance. The negative programming version also exists.
- Positive - TryValidate.
- Negative - Validate.
On this link, you will get the information about Exceptions and Performance.
The examples class
The class for all examples will be a new version of the class created in part I.
- public class Customer
- {
- [Required(ErrorMessage = "{0} is mandatory")]
- [MaxLength(50, ErrorMessage = "The {0} can not have more than {1} characters")]
- public string Name { get; set; }
- [Range(typeof(DateTime), "01/01/2016", "01/01/2050",
- ErrorMessage = "Valid dates for the Property {0} between {1} and {2}")]
- public DateTime EntryDate { get; set; }
- public string Password { get; set; }
- [Compare("Customer.Password", ErrorMessage = "The fields Password and PasswordConfirmation should be equals")]
- public string PasswordConfirmation { get; set; }
- [Range(0, 150, ErrorMessage = "The Age should be between 0 and 150 years")]
- public int Age { get; set; }
- }
ValidationResult
ValidationResult is a container for class validation results. For more info, go here.
ValidationResult has 2 properties
- ErrorMessages .- String readonly property with the information error description.
- MemberNames.- IEnumerable<string> readonly property with the property name on error.
We have written an extension method to print the validation errors.
- public static string ToDescErrorsString(this IEnumerable<ValidationResult> source, string mensajeColeccionVacia = null)
- {
- if (source == null) throw new ArgumentNullException(nameof(source), $"The property {nameof(source)}, doesn't has null value");
- StringBuilder resultado = new StringBuilder();
- if (source.Count() > 0)
- {
- resultado.AppendLine("There are validation errors:");
- source.ToList()
- .ForEach(
- s =>
- resultado.AppendFormat(" {0} --> {1}{2}", s.MemberNames.FirstOrDefault(), s.ErrorMessage,
- Environment.NewLine));
- }
- else
- resultado.AppendLine(mensajeColeccionVacia ?? string.Empty);
- return resultado.ToString();
- }
Validator class
This is the static helper class. The Validator class allows you to execute validation on objects, properties, and methods. You can get more information from this link.
We can separate its methods in two groups, as we saw earlier.
This is the static helper class. The Validator class allows you to execute validation on objects, properties, and methods. You can get more information from this link.
We can separate its methods in two groups, as we saw earlier.
POSITIVE PROGRAMMING (Returns bool value and we have a ICollection<ValidationResult> parameter)
The return property bool is a validation result.
The ICollection<ValidationResult> argument contains details of validation errors. If the validation doesn't have errors, this collection will be empty.
TryValidateObject
- public static bool TryValidateObject(object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults);
- public static bool TryValidateObject(object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults, bool validateAllProperties);
Arguments
- Instance The instance of class to validate.
- ValidationContext The context that describes the object to validate.
- ValidationResults The collection of validation results descriptions.
- ValidateAllProperties Enabled continues to validate all properties.
Example
- public static void TryValidateObjectExample1()
- {
- /// 1.- Create a customer
- var customer = new Customer
- {
- Name = string.Empty,
- EntryDate = DateTime.Today,
- Password = "AAAA",
- PasswordConfirmation = "BBBB",
- Age = -1
- };
- /// 2.- Create a context of validation
- ValidationContext valContext = new ValidationContext(customer, null, null);
- /// 3.- Create a container of results
- var validationsResults = new List<ValidationResult>();
- /// 4.- Validate customer
- bool correct = Validator.TryValidateObject(customer, valContext, validationsResults, true);
- Console.WriteLine(validationsResults.ToDescErrorsString("Without Errors !!!!"));
- Console.Read();
- }
Result

We have validated all customer properties.
If we change the last argument to false, it only validates the first property on error.
- public static void TryValidateObjectExample2()
- {
- /// 1.- Create a customer
- var customer = new Customer
- {
- Name = string.Empty,
- EntryDate = DateTime.Today,
- Password = "AAAA",
- PasswordConfirmation = "BBBB",
- Age = -1
- };
- /// 2.- Create a context of validation
- ValidationContext valContext = new ValidationContext(customer, null, null);
- /// 3.- Create a container of results
- var validationsResults = new List<ValidationResult>();
- /// 4.- Validate customer
- bool correct = Validator.TryValidateObject(customer, valContext, validationsResults, false);
- Console.WriteLine(validationsResults.ToDescErrorsString("Without Errors !!!!"));
- Console.Read();
- }

TryValidateProperty
- public static bool TryValidateProperty(object value, ValidationContext validationContext, ICollection<ValidationResult> validationResults);
- public static void TryValidatePropertyExample()
- {
- /// 1.- Create a customer
- var customer = new Customer
- {
- Name = string.Empty,
- EntryDate = DateTime.Today,
- Password = "AAAA",
- PasswordConfirmation = "BBBB",
- Age = -1
- };
- /// 2.- Create a context of validation
- ValidationContext valContext = new ValidationContext(customer, null, null)
- {
- MemberName = "Age"
- };
- /// 3.- Create a container of results
- var validationsResults = new List<ValidationResult>();
- /// 4.- Validate customer Age Property
- bool correct = Validator.TryValidateProperty(customer.Age, valContext, validationsResults);
- Console.WriteLine(validationsResults.ToDescErrorsString("Without Errors !!!!"));
- Console.Read();
- }
When we instance the ValidationContext object, we give value to string property MemberName with the property name to validate.
The TryValidateProperty and the TryValidateObject are equal. The only change is the first parameter. The TryValidateProperty will have to call the property value.
Result

TryValidateValue
- public static bool TryValidateValue(object value, ValidationContext validationContext, ICollection<ValidationResult> validationResults, IEnumerable<ValidationAttribute> validationAttributes);
- public static void TryValidateValueExample()
- {
- /// 1.- Create value
- string myPwd = "33223";
- /// 2.- Create ValidationsAttributes
- MinLengthAttribute minLengthAtribute = new MinLengthAttribute(8) { ErrorMessage = "{0} must have {1} caracters minimum" };
- RequiredAttribute requieredAttribute = new RequiredAttribute { ErrorMessage = "{0} is mandatory" };
- List<ValidationAttribute> atributes = new List<ValidationAttribute>() { minLengthAtribute, requieredAttribute };
- /// 3.- Create a context of validation
- ValidationContext valContext = new ValidationContext(myPwd, null, null)
- {
- MemberName = "myPwd"
- };
- /// 4.- Create a container of results
- var validationsResults = new List<ValidationResult>();
- /// 5.- Validate myPwd value
- bool correct = Validator.TryValidateValue(myPwd, valContext, validationsResults, atributes);
- Console.WriteLine(validationsResults.ToDescErrorsString("Without Errors !!!!"));
- Console.Read();
- }
Result

NEGATIVE PROGRAMMING (throw ValidationException and it hasn’t ICollection<ValidationResult argument )
These methods remove the word Try in your names. They are void methods. If the validation fails, it will throw a ValidationException.
They don’t have an ICollection<ValidationResult> argument. This information will have an inside exception and it isn’t a collection. But, it is a simple ValidationResult because if validation fails, it doesn’t verify the remaining properties.
They don’t have an ICollection<ValidationResult> argument. This information will have an inside exception and it isn’t a collection. But, it is a simple ValidationResult because if validation fails, it doesn’t verify the remaining properties.
- public static void ValidateObject(object instance, ValidationContext validationContext);
- public static void ValidateObject(object instance, ValidationContext validationContext, bool validateAllProperties);
- public static void ValidateProperty(object value, ValidationContext validationContext);
- public static void ValidateValue(object value, ValidationContext validationContext, IEnumerable<ValidationAttribute> validationAttributes);
- public static void ValidateObjectExample()
- {
- /// 1.- Create a customer
- var customer = new Customer
- {
- Name = string.Empty,
- EntryDate = DateTime.Today,
- Password = "AAAA",
- PasswordConfirmation = "BBBB",
- Age = -1
- };
- /// 2.- Create a context of validation
- ValidationContext valContext = new ValidationContext(customer, null, null);
- try
- {
- /// 3.- Validate customer
- Validator.ValidateObject(customer, valContext, true);
- }
- catch (ValidationException ex)
- {
- /// 4.- Print Validations Results
- ValidationResult s = ex.ValidationResult;
- Console.WriteLine("There are validation errors:");
- Console.WriteLine(" {0,-20} --> {1}{2}", s.MemberNames.FirstOrDefault(), s.ErrorMessage,
- Environment.NewLine);
- }
- Console.Read();
- }

The other methods are same as the ‘Try’ version.
Considerations and tests
Remember, we can use the extension method of Chapter I.
You have the source code to test the examples.

Anu VPosted Dec 14, 2016, 6:58 AM
Nice.. Thanks for sharing..
Jaco ZwartsPosted Dec 9, 2016, 1:25 AM
Interesting good read Juan, thank you for sharing