How to make WinForm perform Model validation? If you have experience in asp.net mvc development, you will know that we can call ModelState.IsValid to verify the model. This is to verify the legality of the data submitted by the client from a security or business perspective.
WinForm perform Model validation
For Winform development, we need to encapsulate and provide similar functions by ourselves. For Winform development, we need to encapsulate ourselves to provide similar functions. In addition, you can also find similar posts on stackoverflow. This article also shares how I did it based on these methods.For Winform development, we need to encapsulate ourselves to provide similar functions. In addition, you can also find similar posts on stackoverflow. This article also shares how I did it based on these methods.
The following content is derived from a post on c-sharpcorner.com. I think this post is very good and can help you learn some useful knowledge.
Validation Forms In DataAnnotations
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; } }
These are principal validation classes.
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. 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);
This method validates all objects. TryValidateObject has an overload with a bool argument validateAllProperties that is enabled in case when validation error continues with the validation of all properties.
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(); }
In this example, we have done the second overload with true value (ValidateAllProperties).
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(); }
WinForm perform Model validation
Result
TryValidateProperty
public static bool TryValidateProperty(object value, ValidationContext validationContext, ICollection<ValidationResult> validationResults);
WinForm perform Model validation
It has only one overload. It has the same parameters as of TryValidateObject, but the first object parameter does match with one property to validate and the method, therefore, validates properties.
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(); }
WinForm perform Model validation
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);
WinForm perform Model validation
TryValidateValue validates a value through ValidationAttribute collection. This is practical to reuse our ValidationAttributes and for us to be disabused of the if terms.
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(); }
WinForm perform Model validation
We have created the attributes in code, because we will validate a value and we don’t have properties to mark in the class declaration.
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.
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);
WinForm perform Model validation
Example
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(); }
Result
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.