29. Using Model Validation Flashcards
What is Model Validation?
Model validation is the process of ensuring that the data provided in a request is valid for use in the application.
Model validation is the process of ensuring the data received by the application is suitable for binding to the model and, when this is not the case, providing useful information to the user that will help explain the problem.
Why is Model Validation useful?
Users do not always enter valid data, and using it in the application can produce unexpected and undesirable errors.
The first part of the process, checking the data received, is one of the most important ways to preserve the integrity of an application’s data. Rejecting data that cannot be used can prevent odd and unwanted states from arising in the application. The second part of the validation process is helping the user correct the problem and is equally important. Without the feedback needed to correct the problem, users become frustrated and confused.
How is Model Validation used?
Controllers and Razor Pages check the outcome of the validation process, and tag helpers are used to include validation feedback in views displayed to the user. Validation can be performed automatically during the model binding process and can be supplemented with custom validation.
Are there any pitfalls or limitations to Model Validation?
It is important to test the efficacy of your validation code to ensure that it covers the full range of values that the application can receive.
Are there any alternatives to Model Validation?
Model validation is optional, but it is a good idea to use it whenever using model binding.
Why is model validation so important?
Model validation is the process of enforcing the requirements that an application has for the data it receives from clients. Without validation, an application will try to operate on any data it receives, which can lead to exceptions and unexpected behavior that appear immediately or long-term problems that appear gradually as the database is populated with bad, incomplete, or malicious data.
What is the most direct way of validating data?
in an action or handler method,
What is the ModelStateDictionary class?
A dictionary used to track details of the state of the model object, with an emphasis on validation errors.
What are the 4 most important ModelStateDictionary members? And give a brief description.
AddModelError(property, message)
This method is used to record a model validation error for the specified property.
GetValidationState(property)
This method is used to determine whether there are model validation errors for a specific property, expressed as a value from the ModelValidationState enumeration.
getValidationState method is used to see whether there have been any errors recorded for a model property, either from the model binding process or because the AddModelError method has been called during explicit validation in the action method. The GetValidationState method returns a value from the ModelValidationState enumeration, which defines the values described in Table 29-4.
IsValid
This property returns true if all the model properties are valid and returns false otherwise.
Clear()
This property clears the validation state.
What are the 4 ModelValidationState Values and what do they mean?
Unvalidated
This value means that no validation has been performed on the model property, usually because there was no value in the request that corresponded to the property name.
Valid
This value means that the request value associated with the property is valid.
Invalid
This value means that the request value associated with the property is invalid and should not be used.
Skipped
This value means that the model property has not been processed, which usually means that there have been so many validation errors that there is no point continuing to perform validation checks.
Consider how the Name property was validated.
…
if (string.IsNullOrEmpty(product.Name)) {
ModelState.AddModelError(nameof(Product.Name), “Enter a name”);
}
…
One of the validation requirements for the Product class is to ensure the user provides a value for the Name property, so I use the static string.IsNullOrEmpty method to test the property value that the model binding process has extracted from the request. If the Name property is null or an empty string, then I know that the value cannot be used by the application, and I use the ModelState.AddModelError method to register a validation error, specifying the name of the property (Name) and a message that will be displayed to the user to explain the nature of the problem (Enter a name).
Is the ModelStateDictionary is also used during the model binding process?
The ModelStateDictionary is also used during the model binding process to record any problems with finding and assigning values to model properties.
Consider how the Price property was validated.
…
if (ModelState.GetValidationState(nameof(Product.Price))
== ModelValidationState.Valid && product.Price < 1) {
ModelState.AddModelError(nameof(Product.Price), “Enter a positive price”);
}
…
For the Price property, I check to see whether the model binding process has reported a problem parsing the value sent by the browser into a decimal value.
I want to make sure that the user provides a Price value that is equal to or greater than 1, but there is no point in recording an error about zero or negative values if the user has provided a value that the model binder cannot convert into a decimal value. I use the GetValidationState method to determine the validation status of the Price property before performing my own validation check.
Consider the following code? ... if (ModelState.IsValid) { TempData["name"] = product.Name; TempData["price"] = product.Price.ToString(); TempData["categoryId"] = product.CategoryId.ToString(); TempData["supplierId"] = product.SupplierId.ToString(); return RedirectToAction(nameof(Results)); } else { return View("Form"); } ...
After I have validated all the properties in the Product object, I check the ModelState.IsValid property to see whether there were errors. This method returns true if the Model.State.AddModelError method was called during the checks or if the model binder had any problems creating the object.
The Product object is valid if the IsValid property returns true, in which case the action method redirects the browser to the Results action, where the validated form values will be displayed. There is a validation problem if the IsValue property returns false, which is dealt with by calling the View method to render the Form view again.
What happens if there were any errors?
If the IsValue property returns false, it will be dealt with by calling the View method to render the Form view again.
It may seem odd to deal with a validation error by calling the View method, but the context data provided to the view contains details of the model validation errors; these details are used by the tag helper to transform the input elements.
What happens to an element
The input element will be transformed. Here is the input element before the form was submitted:
Here is the input element after the form has been submitted:
The tag helper adds elements whose values have failed validation to the input-validation-error class, which can then be styled to highlight the problem to the user.
How do you style input elements that have an invalid value?
You can do this by defining custom CSS styles in a stylesheet, but a little extra work is required if you want to use the built-in validation styles that CSS libraries like Bootstrap provides. The name of the class added to the input elements cannot be changed, which means that some JavaScript code is required to map between the name used by ASP.NET Core and the CSS error classes provided by Bootstrap.
Consider the following javascript
$(document).ready(function () { $("input.input-validation-error").addClass("is-invalid"); });
It is used as a partial view in forms. It contains a script element that loads the jQuery library and contains a custom script that locates input elements that are members of the input-validation-error class and adds them to the is-invalid class (which Bootstrap uses to set the error color for form elements).
What is the ValidationSummaryTagHelper class used for?
The ValidationSummaryTagHelper class detects the asp-validation-summary attribute on div elements and responds by adding messages that describe any validation errors that have been recorded.
<div></div>
The value of the asp-validation-summary attribute is a value from the ValidationSummary enumeration
All:
This value is used to display all the validation errors that have been recorded.
ModelOnly:
This value is used to display only the validation errors for the entire model, excluding those that have been recorded for individual properties, as described in the “Displaying Model-Level Messages” section.
None:
This value is used to disable the tag helper so that it does not transform the HTML element.
How to Display Property-Level Validation Messages? And what are Property-Level validation messages?
Although the custom error message is more meaningful than the default one, it still isn’t that helpful because it doesn’t clearly indicate which field the problem relates to. For this kind of error, it is more useful to display the validation error messages alongside the HTML elements that contain the problem data. This can be done using the ValidationMessageTag tag helper, which looks for span elements that have the asp-validation-for attribute, which is used to specify the property for which error messages should be displayed.
<div><span></span></div>
Explain the DefaultModelBindingMessageProvider class
The model binder has a set of predefined messages that it uses for validation errors. These can be replaced with custom messages using the methods defined by the DefaultModelBindingMessageProvider class.
Add this in the startup class in order to create custom error message. services.Configure(opts => opts.ModelBindingMessageProvider .SetValueMustNotBeNullAccessor(value => "Please enter a value"));
Description of SetValueMustNotBeNullAccessor:
The function assigned to this property is used to generate a validation error message when a value is null for a model property that is non-nullable.
How are validation errors that relate to the entire model recorded ?
Validation errors that relate to the entire model are recorded using the AddModelError with the empty string as the first argument.
ModelState.AddModelError(“”, “Small products cannot cost more than $100”);
Is the validation done the same way in pages, as in views/controller?
Yes, pretty much
How to to express model validation rules directly in the model class?
Added to properties in model classes.
The validation process supports the use of attributes to express model validation rules directly in the model class, ensuring that the same set of validation rules will be applied regardless of which action method is used to process a request.
The validation attributes are applied before the action method is called, which means that I can still rely on the model state to determine whether individual properties are valid when performing model-level validation.
Example:
[Required(ErrorMessage = “Please enter a price”)]
[Range(1, 999999, ErrorMessage = “Please enter a positive price”)]
public decimal Price { get; set; }