Model Validation in ASP.NET Core MVC

In this tutorial, we look at how ASP.NET core Model Validation works. Often the data entered by the user is not valid and cannot be saved into the database. The entered data may contain a typo or user may intentionally enter the inappropriate data. Hence, we need to validate the user input before storing it in the database. The ASP.NET Core gives us Model Validator, which uses the validation attributes to validate the model, which makes our task easier. We also take a look at ModelState and how to use it. Finally, we look at the list of Validation attributes.

Introduction to Model Validation

The Form Data is posted to Controller action is automatically mapped to the action parameter by the Model Binder. We already looked at how Model Binding works in ASP.NET Core.

The Model needs to be validated for the correctness. These validations can be done at the client side before sending data to the server or at the server side when the data is received from the client. The client-side validation is important because of better user experience, while the server side validation should ensure that the invalid data does not enter the system.

Importance of client-side Validation

  • Better User experiences
  • Since the validation happens in the client’s browser, the Response is faster and immediate.
  • Saves Precious server resources bandwidth by Minimizing the Server round trips
  • Since there is no HTTP Request/response round trip involved in the validation, It saves bandwidth & Server resources

Importance of server-side Validation

The client-side validation gives a better user experience, but not trustworthy. It may fail for many no of reasons. For Example.

  • The Javascript may be disabled in the end users browser.
  • The Malicious user can send the data directly to the user, without using the application or use some interceptor modify the HTTP Request.
  • An Error in Javascript code may result in validation to succeed although data is invalid.

Hence, it is important to validate the data completely at the server side, even though you have done those validations at the client side.

Explicitly Validating a Model

Once you received the model in the controller, you can validate the model programmatically as shown below.

The above code just checks for whether the Name property is empty or null.

The above code works fine, but you may have several such properties in the model, where you need to check for the similar condition. Also, we need to figure out how to send the validation error messages to the client side so as to display it to the user.

The Model Validator does all these for us, without writing a single line of code.

How Model Validation works

We learnt how Model binding works in ASP.NET Core applications. When the HTTP Request arrives Model binder is invoked before passing the control to controller action method. The Model binder not only binds the value to the action parameter but also validates them by using the Model Validator.

The Model Validator runs after the model binding and runs a series of validations on each property of the model based on the attributes that you set on the model property. These attributes are called Validation attributes and contain the code, which is used by the Model Validator to validate the model.

How ASPNET Model Binding works

All these Validations runs on the server side,

The ASP.NET Core has lots of built-in Validation attributes, which can be added to the properties in a model, to enforce the validation rule. These Validation attributes also known as DataAnnotations and are available in System.ComponentModel.DataAnnotations namespace. You need to import it in your ViewModel to use them.

For Example, you can mark the field as required using the attribute [Required].

The Model binder does not throw any errors if the validation failed. But it updates the ModelState object with the list of errors and sets the isValid property to false before it invokes the action method.

We need to check the ModelState.isValid property to know whether the validation is failed and take appropriate action based on that like returning the list of errors to the client

How to Use Validation Attributes

Updating the Model with Data Annotation attribute

In the Model, Property adds the Data Annotation Attribute as shown below. The code below adds two validation attributes to the Name property. It also passes the custom error message to be displayed to the user in case of error.

View to display Validation error messages

In the View, use the Validation tag helpers to display the error message to the user.

The asp-validation-summary tag helper displays the list of Model Only Validation error messages at the top of the form. It is attached to the div element and placed at the top of the form.

The asp-validation-for displays the error message of the Name property right next to it. It is attached to the span element and placed next to the property.

The Validation tag helpers insert the field-validation-error & validation-summary-errors classes in the HTML if the errors are found. Hence we added the styles to display the error messages in the red on those classes.

You can read more about Validation Tag Helpers from this tutorial.

Check ModelState.isValid in the controller Action

Finally, in the Controller action method, check if ModelState.IsValid to check if there is any error. In case of error return the View(model) back to the user.

We passing the model to view so that it can repopulate the values entered by the user. The Validation errors are inserted in the View by the Validation tag helpers.

The following image shows the validation error messages displayed.

Example of Model Validation in ASP.NET Core

ModelState

The Model Binder updates the ModelState object, with the result of Model Binding & validation. The ModelState keeps track of the details of the values submitted to model along with the validation errors that occurred for each property of the model.

The ModelState is a Property of the ControllerBase class and is of type ModelStateDictionary Object.

ModelState properties

PropertyTypeRemarks
KeysKeyEnumerableGets the key sequence. The collection of model properties' names. Keys Property gives you Access to state of individual model properties
ValuesValueEnumerableThe model properties' values Get the value sequence.
MaxAllowedErrorsGets or sets the maximum allowed model state errors in this instance of ModelStateDictionary. Defaults to 200.
HasReachedMaxErrorsboolGets a value indicating whether or not the maximum number of errors have been recorded.
IsValidboolWhether or not the model is valid
ItemModelStateEntryAccess to individual model properties' state
CountIntThe count of model properties
ErrorCountintThe number of errors that are added to this instance of ModelStateDictionary via AddModelError or TryAddModelError.

Methods of ModelState

AddModelError

Adds the specified error message to the Errors instance that is associated with the specified key.

Clear

Removes all keys and values from this instance of ModelStateDictionary.

ClearValidationState(String)

Clears ModelStateDictionary entries that match the key that is passed as the parameter.

GetFieldValidationState(String)

Returns the aggregate ModelValidationState for items starting with the specified key.

GetValidationState(String)

Returns ModelValidationState for the key.

TryAddModelError(String, Exception, ModelMetadata)

Attempts to add the specified exception to the Errors instance that is associated with the specified key.

Example of using ModelState

Getting the List of Errors

Looping through the keys to get the list of Errors in the ModelState

Adding Custom Error Messages

Not all errors can be validated by the Model Validator. For Example, you got a valid Product Model, but the Product already exists in the Database.

In such cases, you can add the custom error messages to the ModelState and send it back to the user

List of Validation Attributes

We looked at Required & StringLength attributes in the previous example. The System.ComponentModel.DataAnnotations namespace contains several such attributes. Here is the list of available attributes.

CreditCard

Validates the property has a credit card format.

Example

Compare

Compares the value with the value of other properties.

Example

Compare attribute is applied to the confirmPassword field. The OtherProperty argument property name is passed (“NewPassword”)

If ConfirmPassword does not match with the NewPassword, then the validation fails.

Alternatively, you can make the comparison in an property get method and do some additional checking etc.

EmailAddress

Validates the property has an email format.

Example

The following HTML generated

As you can see in the HTML, the type attribute is set to email. In this case, the browser displays an error message if there is an invalid email ID.

Phone

Validates the property has a telephone format.

Example

Range

Enables you to validate whether the value of a property falls between a specified range of values.

RegularExpression

Validates that the data matches the specified regular expression.

Example

Required

Makes a property required. Enables you to mark a property as required.

The Non-nullable value types (such as decimal, int, float, and DateTime) are inherently required and don’t need the Required attribute. The app performs no server-side validation checks for non-nullable types that are marked Required.

StringLength

Validates that a string property has at most the given maximum length.

Example

Url

Validates the property has a URL format.

The following HTML generated

Summary

We looked at How Model Validator works in ASP.NET Core applications. This Validation happens at the Server side. You also need to validate the Model at the client side, which is covered in the next tutorial.

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top