As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened,
visit the help center for guidance.
Closed 7 years ago.
Is there a best practice way to validate user input?
Actual Problem:
A user gives certain inputs in a window. When he is done with those inputs, he can click 'create'. Now, a pop up message should be shown with all invalid input given. If no invalid input, then just continue.
I could easily do this in the Form class. But I remember some best practice way of validating the input in the set properties. Problem is that I already created an instance of that class (or otherwise, can't set properties ;) ) if I validate this way. That should not happen, no instance of the class may be created unless input is valid.
I was planning to create a ErrorMessages class that contains a list where I can put all errorMessages. Every time an invalid input is given, a new message is added to the errorMessages list. So if user click's 'create' button, all messages in the list are shown. Is this a good way of handling things?
So is there a best practice way? Any design patterns that provide such solution?
Edit: This is a school task. So with illogical requirements. I HAVE to show all invalid inputs when I click 'create'. I would like to do this out of Form class. (So validation works even without GUI, I did't even create the GUI yet at this point). First making sure my functionality works correctly ;). I want to keep my code clean, abstract and OOP. So how should I show my error messages?
I was planning to create a ErrorMessages class that contains a list where I can put all errorMessages. Every time an invalid input is given, a new message is added to the errorMessages list. So if user click's 'create' button, all messages in the list are shown. Is this a good way of handling things?
Subjectively, I think it would be better to provide instant feedback that the value the user entered is invalid. That way, they can immediately go back and fix it.
I mean, think about it. The approach you propose would literally give them a giant list of problems at the end, which is not very user-friendly. Besides, how are they going to remember all of those problems to be able to go back and fix them one at a time? (Hint: they're not.)
Instead, I recommend using the ErrorProvider
class to display any errors right next to the appropriate control. I talked a little bit more about this approach in my answer here and here.
Of course, you'll still need to make sure upon final submission (clicking the OK/Submit button) that all the input is valid, but then that's just a simple case of checking for the presence of any errors.
I could easily do this in the Form class. But I remember some best practice way of validating the input in the set properties.
Yes, the idea here is encapsulation. The Form class should only know about form stuff. It shouldn't be required to know what kind of input is/is not valid for all of your different controls.
Instead, this validation logic should be placed elsewhere, such as in a class that stores your data. That class would expose public properties to get and set the data, and inside of the setter method, it would verify the data.
That means that all your Form has to do is call a setter method on your data class. The Form needs to know nothing about how to validate the data, or even what the data means, because the data class handles all of that.
That should not happen, no instance of the class may be created unless input is valid.
If this is indeed the case, you will need to provide a constructor for the class that accepts as parameters all of the data it needs. The body of the constructor will then validate the specified data and throw an exception if any of it is invalid. The exception will prevent the class from being created, ensuring that no instance of a class that contains invalid data ever exists.
Such a class would probably not have setter methods at all—only getters.
However, this is kind of an unusual requirement in the world of C# (however common it may be in C++). Generally, placing your validation code inside of the setters works just fine.
My properties have some private setters. So they only get set in the constructor of my data class. Problem is now that this seems to make my validation not eassy
Why would that change anything? You still handle the validation inside of the private setters. If validation fails, you throw an exception. Because the constructor doesn't handle the exception, it continues bubbling up out of that method to the code that attempted to instantiate the object. If that code wants to handle the exception (e.g., to display an error message to the user), it can do so.
Granted, throwing an exception in the case of invalid input is not necessarily a "best practice". The reason is that exceptions should generally be reserved for unexpected conditions, and users screwing up and providing you with invalid data is, well, to be expected. However:
- This is the only option you have for data validation inside of a constructor, because constructors can't return values.
- The cost of exception handling is basically negligible in UI code since modern computers can process exceptions faster than users can perceive on-screen changes.
This is a simple requirement but sometimes being debated. This is my "current" approach how to deal with validation. I have not yet used this approach, and this is just a concept. This approach need to be developed more
First, create a custom validation attributes
public class ValidationAttribute : Attribute{
public type RuleType{get;set;}
public string Rule{get;set;}
public string[] RuleValue{get;set;}
}
Second, create a custom error handler / message
public class ValidationResult{
public bool IsSuccess{get;set;};
public string[] ErrorMessages{get;set;};
}
Then create a validator
public class RuleValidator{
public ValidationResult Validate(object o){
ValidationResult result = new ValidationResult();
List<string> validationErrors = new List<string>();
PropertyInfo[] properties = o.GetType().GetProperties();
foreach(PropertyInfo prop in properties){
// validate here
// if error occur{
validationErrors.Add(string.Format("ErrorMessage at {0}", prop.Name));
//}
}
result.ErrorMessages = validationErrors.ToArray();
}
}
To use it, then you can do like this:
public class Person{
[ValidationAttribute(typeof(string), "Required", "true")]
public string Name{get;set;}
[ValidationAttribute(typeof(int), "Min", "1")]
public int Age{get;set;}
}
To call the validator
public void ValidatePerson(Person person){
RuleValidator validator = new RuleValidator();
ValidationResult result = validator.Validate(person);
// generate the error message here, use result.ErrorMessages as source
}
What is the advantage:
- You can use in any application platform (Winforms, Asp.Net, WCF,
etc)
- You can set the rule in attribute-level
- It can do automated validation
- This approach can be used with DependencyInjection with custom
validators to separate validation logics
The disadvantage:
- Hard to create the validators
- If not handled well, the validators can become very large in number
- Bad performance due to use of reflection
See the ErrorProvider
class (documentation here). It provides a set of standard visual indicators that can be attached to most of the standard WinForms controls.
There are several possible approaches:
- Use "instant" validation.
When user enters value it is checked during input (TextChanged
) and validated right away. Create instance of a new class, call property/method what should accept string
and return bool
(or throw Exception
in case of property), on false
- draw special error condition (red label next to text box, something blinking, ErrorProvider
or whatever you can do what should tell user "wrong!").
This one I like to use, but a bit differently, usually I only check Type
and then just trying to parse it straight away in the form. It is possible to abstract more if form operate with the string
's and all formattings and validation occurs in the class (property setters). Or you can supply form with additional information (by using query methods or attributes) so it can do instant validation without need to instantiate class or using setters. As example, double factor
property can be identified in the form (or even control) to perform 'double.Parseand you can have attribute
DefaultValuewhich can be used to display to the user value in the different way when it's different from default (like it is done by
PropertyGrid`).
When user finished input, validate (by trying to set value and catching exception), if wrong - user can't "leave" or "progress" until he press ESC (to cancel changes) or correct his input to pass validation.
This one I dislike. Idea of holding user annoy me (and user ofc). Also it is hard to implement cross checks (like if you have Min
and Max
values, then user will be pushed to increase "right" one first, otherwise invalidation will fail).
That just means let user to enter everything and only validate when he clicks "Ok" button.
I think combining "Ok" button and interactive instant validation is the best for the user. As user knows where he made a mistake through input, but still is free to browse and only will get a "slap" from validation after clicking "Ok" button (at which step you can simply show him first of errors he did, not necessary to show them all).
Error messages can be provided by setters in the old-fashion LastError
way or as a text in the Exception
.