29. Using Model Validation Flashcards

1
Q

What is Model Validation?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Why is Model Validation useful?

A

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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

How is Model Validation used?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Are there any pitfalls or limitations to Model Validation?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Are there any alternatives to Model Validation?

A

Model validation is optional, but it is a good idea to use it whenever using model binding.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Why is model validation so important?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is the most direct way of validating data?

A

in an action or handler method,

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What is the ModelStateDictionary class?

A

A dictionary used to track details of the state of the model object, with an emphasis on validation errors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What are the 4 most important ModelStateDictionary members? And give a brief description.

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What are the 4 ModelValidationState Values and what do they mean?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Consider how the Name property was validated.


if (string.IsNullOrEmpty(product.Name)) {
ModelState.AddModelError(nameof(Product.Name), “Enter a name”);
}

A

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).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Is the ModelStateDictionary is also used during the model binding process?

A

The ModelStateDictionary is also used during the model binding process to record any problems with finding and assigning values to model properties.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

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”);
}

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q
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");
}
...
A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What happens if there were any errors?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What happens to an element

A

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.

17
Q

How do you style input elements that have an invalid value?

A

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.

18
Q

Consider the following javascript

$(document).ready(function () {
    $("input.input-validation-error").addClass("is-invalid");
});
A
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).
19
Q

What is the ValidationSummaryTagHelper class used for?

A

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.

20
Q

How to Display Property-Level Validation Messages? And what are Property-Level validation messages?

A

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>

21
Q

Explain the DefaultModelBindingMessageProvider class

A

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.

22
Q

How are validation errors that relate to the entire model recorded ?

A

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”);

23
Q

Is the validation done the same way in pages, as in views/controller?

A

Yes, pretty much

24
Q

How to to express model validation rules directly in the model class?

A

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; }

25
Q

What’s the mishap of putting validation logic into an action method?

A

that it ends up being duplicated in every action or handler method that receives data from the user. To help reduce duplication, 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.

26
Q

What are the 5 Built-in Validation Attributes?

A

Compare
[Compare (“OtherProperty”)]
This attribute ensures that properties must have the same value, which is useful when you ask the user to provide the same information twice, such as an e-mail address or a password.

Range
[Range(10, 20)]
This attribute ensures that a numeric value (or any property type that implements IComparable) is not outside the range of specified minimum and maximum values. To specify a boundary on only one side, use a MinValue or MaxValue constant.

RegularExpression
[RegularExpression (“pattern”)]
This attribute ensures that a string value matches the specified regular expression pattern. Note that the pattern must match the entire user-supplied value, not just a substring within it. By default, it matches case sensitively, but you can make it case insensitive by applying the (?i) modifier—that is, [RegularExpression(“(?i)mypattern”)].

Required
[Required]
This attribute ensures that the value is not empty or a string consisting only of spaces. If you want to treat whitespace as valid, use [Required(AllowEmptyStrings = true)].

StringLength
[StringLength(10)]
This attribute ensures that a string value is no longer than a specified maximum length. You can also specify a minimum length: [StringLength(10, MinimumLength=2)].

27
Q

How to create a Custom Property Validation Attribute?

A

The validation process can be extended by creating an attribute that extends the ValidationAttribute class.

Custom attributes override the IsValid method, which is called with the value to check, and a ValidationContext object that provides context about the validation process and provides access to the application’s services through its GetService method.
In Listing 29-16, the custom attribute receives the type of an Entity Framework Core database context class and the type of a model class. In the IsValid method, the attribute obtains an instance of the context class and uses it to query the database to determine whether the value has been used as a primary key value.

Custom validation attributes can also be used to perform model-level validation.

Property-level custom validation attributes are applied directly to the properties they validate, and model-level attributes are applied to the entire class

The validation attributes are applied automatically before the action method is invoked, which means that the validation outcome can be determined simply by reading the ModelState.IsValid property.

Expressing the validation through the custom attributes removes the code duplication between the controller and the Razor Page and ensures that validation is applied consistently wherever model binding is used for Product objects.

28
Q

What is client-side validation?

A

In web applications, users typically expect immediate validation feedback—without having to submit anything to the server. This is known as client-side validation and is implemented using JavaScript. The data that the user has entered is validated before being sent to the server, providing the user with immediate feedback and an opportunity to correct any problems.
ASP.NET Core supports unobtrusive client-side validation. The term unobtrusive means that validation rules are expressed using attributes added to the HTML elements that views generate. These attributes are interpreted by a JavaScript library distributed by Microsoft that, in turn, configures the jQuery Validation library, which does the actual validation work.

29
Q

What is remote validation?

A

Remote validation blurs the line between client- and server-side validation: the validation checks are enforced by the client-side JavaScript code, but the validation checking is performed by sending an asynchronous HTTP request to the application to test the value entered into the form by the user.
A common example of remote validation is to check whether a username is available in applications when such names must be unique, the user submits the data, and the client-side validation is performed. As part of this process, an asynchronous HTTP request is made to the server to validate the username that has been requested. If the username has been taken, a validation error is displayed so that the user can enter another value.

30
Q

What are the benefits of remote validation compared to server-side validation?

A

This may seem like regular server-side validation, but there are some benefits to this approach. First, only some properties will be remotely validated; the client-side validation benefits still apply to all the other data values that the user has entered. Second, the request is relatively lightweight and is focused on validation, rather than processing an entire model object.
The third difference is that the remote validation is performed in the background. The user doesn’t have to click the submit button and then wait for a new view to be rendered and returned. It makes for a more responsive user experience, especially when there is a slow network between the browser and the server.

31
Q

What is a compromisation of renmote validation?

A

remote validation is a compromise. It strikes a balance between client-side and server-side validation, but it does require requests to the application server, and it is not as quick to validate as normal client-side validation.

32
Q

How is remote validation applied?

A

The first step is to create a web service controller whose action methods will perform the validation checks.

Example of check:
[HttpGet(“categorykey”)]
public bool CategoryKey(string categoryId) {
long keyVal;
return long.TryParse(categoryId, out keyVal)
&& dataContext.Categories.Find(keyVal) != null;
}

Validation action methods must define a parameter whose name matches the field they will validate, which allows the model binding process to extract the value to test from the request query string. The response from the action method must be JSON and can be only true or false, indicating whether a value is acceptable.

To use the remote validation method, I apply the Remote attribute to the CategoryId and SupplierId properties in the Product class like so:

[Remote(“CategoryKey”, “Validation”, ErrorMessage = “Enter an existing key”)]
public long CategoryId { get; set; }

The arguments to the Remote attribute specify the name of the validation controller and its action method. I have also used the optional ErrorMessage argument to specify the error message that will be displayed when validation fails.

Caution: The validation action method will be called when the user first submits the form and again each time the data is edited. For text input elements, every keystroke will lead to a call to the server.

33
Q

What is server-side validation?

A

the user submits their data to the server, and the server validates the data and sends back the results of the validation (either success in processing the data or a list of errors that need to be corrected).

34
Q

What is client-side validation?

A

In web applications, users typically expect immediate validation feedback—without having to submit anything to the server. This is known as client-side validation and is implemented using JavaScript. The data that the user has entered is validated before being sent to the server, providing the user with immediate feedback and an opportunity to correct any problems.
ASP.NET Core supports unobtrusive client-side validation. The term unobtrusive means that validation rules are expressed using attributes added to the HTML elements that views generate. These attributes are interpreted by a JavaScript library distributed by Microsoft that, in turn, configures the jQuery Validation library, which does the actual validation work.
The error message looks like the ones generated by server-side validation, but if you enter text into the field, you will see the error message disappear immediately as the JavaScript code responds to the user interaction

35
Q

How is client-side validation used?

A

The tag helpers add data-val* attributes to input elements that describe validation constraints for fields. Here are the attributes added to the input element for the Name field, for example:


The unobtrusive validation JavaScript code looks for these attributes and performs validation in the browser when the user attempts to submit the form. The form won’t be submitted, and an error will be displayed if there are validation problems. The data won’t be sent to the application until there are no outstanding validation issues.

The JavaScript code looks for elements with the data-val attribute and performs local validation in the browser when the user submits the form, without sending an HTTP request to the server.

One of the nice client-side validation features is that the same attributes that specify validation rules are applied at the client and at the server. This means that data from browsers that do not support JavaScript are subject to the same validation as those that do, without requiring any additional effort.