Model Validations in ASP.NET Core MVC

Model Validations in ASP.NET Core MVC

In this article, I will discuss Model Validations in ASP.NET Core MVC with Examples. Please read our previous article discussing Data Annotations in ASP.NET Core MVC.

Model Validations in ASP.NET Core MVC

Model validations ensure that the data entered by users meets the required criteria before processing or storing it. In ASP.NET Core MVC, Data Annotations provide a simple yet powerful way to enforce validation rules on models, ensuring data integrity, enhancing user experience, and safeguarding our web application against malicious inputs. In this article, I will explain the concept of validations, the types of validations, and how to implement them effectively using Data Annotations in ASP.NET Core MVC.

What are Validations?

Validations in a web application refer to the processes and techniques used to ensure that the data entered by users is accurate, secure, and appropriate before it is processed or stored. Validations help maintain data integrity, enhance user experience, and secure the application from malicious inputs. That means the primary purposes of validations are:

  • Data Integrity: Ensuring data is accurate and consistent.
  • User Experience: Providing immediate and clear feedback to users.
  • Security: Protecting the application from malicious inputs and attacks.
Types of validation:
  • Server-Side Validation: Validates the data on the server, ensuring security and integrity.
  • Client-Side Validation: Validates data in the user’s browser before submission, enhancing user experience by providing immediate feedback.
  • Database Validation: Enforced at the database level, serving as the last line of defense for data integrity by defining constraints at the database level.
Client-Side Validation

Client-side validation uses JavaScript (or similar scripting languages) to validate user input in the browser before it’s sent to the server. It enhances the user experience by providing immediate feedback, like notifying users of an invalid email format.

Benefits:
  • Immediate Feedback: Provides immediate feedback without a server round trip. Users can correct errors immediately.
  • Reduced Server Load: Early detection of errors minimizes the number of invalid requests sent to the server.
  • Improved User Experience: Faster and more responsive forms lead to Improved User Experience.
Limitations:
  • Security Risks: Users can bypass client-side validation by manipulating the client-side code.
  • Performance Issues: Complex validations can slow down the browser, especially on less powerful devices.
Server-Side Validation:

Server-side validation occurs on the server after the form is submitted. Unlike client-side validation, it is the most secure validation method for maintaining data integrity and security since it can’t be bypassed. The following are the Key Points:

  • Uses server-side languages like C#, Java, or Python.
  • The user cannot bypass it.
  • Acts as a backup for client-side validation.
Benefits:
  • Data Integrity: Ensures data meets expected formats and constraints by validating the data types, formats, and rules.
  • Security: Prevents attacks like SQL injection, cross-site scripting (XSS), etc.
  • Enforces Business Rules: Validates more complex business rules that might not be possible on the client side.
Database Validation:

Database Validations are the last line of defense to ensure data consistency across the system. They involve setting constraints directly within the database to prevent invalid data from being stored, such as:

  • Unique Constraints: Ensuring uniqueness of values like usernames or email addresses. That is avoiding duplicate entries.
  • Foreign Keys: Maintaining referential integrity between tables.
  • Check Constraints: Enforce specific rules on data columns, such as age ranges.
Why Use Data Annotation Attributes in ASP.NET Core MVC for Validation?

In modern web development, we need to validate the user input on both the client and server sides. Data Annotations provide a straightforward way to enforce client-side and server-side validations in ASP.NET Core MVC Applications. These attributes are applied directly to the model properties to validate user inputs. By decorating model properties with attributes, we can:

Advantages of Data Annotation Attributes:
  • Simplifies Validation Logic: Automatically validates data without writing extra code.
  • Dual Validation: Ensure the same validation logic applies to the client and server.
  • Built-in Attributes: Provides a wide range of built-in attributes for common validations like [Required], [Range], and [EmailAddress].
  • Custom Data Annotation: We can also create Custom Data Annotation if Built-in Attributes do not fulfill our requirements.
  • Reduce Code Duplication: Centralize validation logic within model classes, making it easier to manage and update.
Built-in Data Annotation Attributes in ASP.NET Core MVC:

ASP.NET Core MVC provides a rich set of built-in Data Annotations Attributes within the System.ComponentModel.DataAnnotations namespace to facilitate model validation. The following are the common Data Annotation Attributes:

  • [Required]: Marks a field as required.
  • [MinLength(length)] & [MaxLength(length)]: Specifies minimum and maximum lengths for string properties.
  • [StringLength(maxLength, MinimumLength = minLength)]: Sets both maximum and optional minimum lengths for string properties.
  • [Range(min, max)]: Restricts a numerical property to a specified range.
  • [EmailAddress]: Validates that a property contains a valid email format.
  • [RegularExpression]: Ensures a property matches a specified regular expression pattern.
  • [Compare(“OtherProperty”)]: Compares the value of one property with another, commonly used for password confirmation.
  • [DataType(type)]: Specifies the data type, such as Date, Time, and Email Address.
  • [Phone]: Validates that a property contains a valid phone number format.
  • [Url]: Ensures that a property contains a valid URL.
  • [CreditCard]: Validates that a property contains a valid credit card format.
Example to Understand Model Validation in ASP.NET Core MVC

Let us understand how to implement model validation using Data Annotations in an ASP.NET Core MVC application. We will build an employee form with the following requirements:

  • Required Fields: Name, Email, Department.
  • Email Format Validation: The email must be in a valid format.
  • Display Validation Errors: Show errors if validation fails.

We want to create the following Employee Form.

Example to Understand Model Validation in ASP.NET Core MVC

We want to make the Name, Email, and Department fields required. If the required values are not provided and the form is submitted, we want to display the required validation errors, as shown in the image below.

Example to Understand Model Validation in ASP.NET Core MVC using Data Annotations

If we enter an Invalid Email, it should display an Invalid Email Format validation error, as shown below.

Model Validation in ASP.NET Core MVC using Data Annotations

If we provide valid data and click on the Create button, it should create the Employee and display the Success message as shown in the below image:

Model Validation in ASP.NET Core MVC

Clicking the Create button with valid data will create the Employee and display the following success message.

Validation in ASP.NET Core MVC

Implementing the Example using Data Annotations in ASP.NET Core MVC:

Let us proceed and see how we can implement the Employee form example using Data Annotation Attributes in an ASP.NET Core MVC Application. First, create a new ASP.NET Core Application using the Model View Controller project template and provide the project name DataAnnotationsDemo.

Creating the Model

First, define the data structure for our application.

Department Enum

Create a class file named Department.cs within the Models folder and then copy and paste the following code. As you can see, this is an Enum representing the different departments.

namespace DataAnnotationsDemo.Models
{
    // Enum representing various departments.
    public enum Department
    {
        None,     // Default value indicating no selection
        HR,       // Human Resources
        Payroll,  // Payroll Department
        IT        // Information Technology
    }
}
Employee Class with Data Annotations

Next, create another class file named Employee.cs within the Models folder and copy and paste the following code. As you can see, we have marked the Name, Email, and Department properties with the Required Attribute, which makes these properties required while performing the model validation. The Required Data Annotation Attribute belongs to the System.ComponentModel.DataAnnotations namespace.

using System.ComponentModel.DataAnnotations;
namespace DataAnnotationsDemo.Models
{
    // Represents an employee with validation rules.
    public class Employee
    {
        public int Id { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Email { get; set; }

        [Required]
        public Department? Department { get; set; } 
    }
}

Note: In addition to Data Annotations, ASP.NET Core offers Fluent API Validations for scenarios requiring more complex validation logic.

Creating Employee Controller

Create a new Empty – MVC Controller with the name EmployeeController and then copy and paste the following code to handle HTTP requests related to the Employee model.

using DataAnnotationsDemo.Models;
using Microsoft.AspNetCore.Mvc;
namespace DataAnnotationsDemo.Controllers
{
    // Controller to manage Employee operations.
    public class EmployeeController : Controller
    {
        //Displays the form to create a new employee.
        public IActionResult Create()
        {
            return View();
        }

        //Handles the form submission for creating a new employee.
        [HttpPost]
        public IActionResult Create(Employee employee)
        {
            // Check if the submitted model passes all validation rules
            if (ModelState.IsValid)
            {
                // TODO: Save the employee data to the database

                // Redirect to the Successful action upon successful creation
                return RedirectToAction("Successful");
            }

            // If validation fails, redisplay the form with validation errors
            return View(employee);
        }

        // Displays a success message after employee creation.
        public IActionResult Successful()
        {
            return View();
        }
    }
}
Code Explanation:
  • Create (GET): Renders the form for creating a new employee.
  • Create (POST): Processes the submitted form. If ModelState.IsValid is true; it proceeds to save the data; otherwise, it returns to the form with validation errors.
  • Successful: Displays a confirmation message upon successful employee creation.
Displaying the Model Validation Error in ASP.NET Core MVC Razor Views:

We need to use asp-validation-for and asp-validation-summary tag helpers to display model validation errors on ASP.NET Core Razor Views. The asp-validation-for tag helper displays a validation message for a single property of our model class. On the other hand, the asp-validation-summary tag helper summarizes all validation errors that occurred on a model.

For example, to display the validation error associated with the Name property of the Employee class, we need to use asp-validation-for tag helper on a <span> element, as shown below.

<div class="form-group row">
    <label asp-for="Name" class="col-sm-2 col-form-label"></label>
    <div class="col-sm-10">
        <input asp-for="Name" class="form-control" placeholder="Enter Your Name">
        <span asp-validation-for="Name"></span>
    </div>
</div>

On the other hand, to display a summary of all validation errors, we need to use the asp-validation-summary tag helper on a <div> element, as shown below.

<div asp-validation-summary=”All”></div>

The value for the asp-validation-summary tag helper can be any of the following.

  • All: When we set the asp-validation-summary attribute to All, it displays all validation messages. This includes messages associated with model properties and messages added to the ModelState without a key (often used for error messages that aren’t tied to a specific field).
  • ModelOnly: Setting the asp-validation-summary attribute to ModelOnly will display only validation messages directly associated with the model properties. This setting excludes any error messages added to the ModelState without a specific key.
  • None: When the asp-validation-summary is set to None, no validation summary is displayed. This option effectively disables the validation summary display.
Creating the Razor Views

Now, let us create the Create and Success Views:

Create View:

So, create a view file named Create.cshtml view under the Views/Employee folder and then copy and paste the following code to render the employee creation form.

@model DataAnnotationsDemo.Models.Employee

@{
    ViewData["Title"] = "Create";
}

<h1>Create Employee</h1>

<!-- Employee Creation Form -->
<div class="row">
    <form asp-controller="Employee" asp-action="Create" method="post" class="mt-3">
        <!-- Validation Summary to display all validation errors -->
        <div asp-validation-summary="All" class="text-danger"></div>
        
        <!-- Name Field -->
        <div class="form-group row">
            <label asp-for="Name" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Name" class="form-control" placeholder="Enter your name" />
                <!-- Displays validation error for Name -->
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
        </div>

        <!-- Email Field -->
        <div class="form-group row">
            <label asp-for="Email" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Email" class="form-control" placeholder="Enter Your Email">
                <!-- Displays validation error for Email -->
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
        </div>

        <!-- Department Field -->
        <div class="form-group row">
            <label asp-for="Department" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <select asp-for="Department" class="form-select"
                        asp-items="Html.GetEnumSelectList<Department>()">
                    <option value="">Please Select</option> <!-- Placeholder option -->
                </select>
                <!-- Displays validation error for Department -->
                <span asp-validation-for="Department" class="text-danger"></span>
            </div>
        </div>

        <!-- Submit Button -->
        <div class="form-group row">
            <div class="col-sm-10 offset-sm-2">
                <button type="submit" class="btn btn-primary">Create</button>
            </div>
        </div>
    </form>
</div>
Here:
  • asp-validation-summary=”All”: Displays a summary of all validation errors.
  • asp-for: Binds the input elements to the model properties.
  • asp-validation-for: Displays validation errors for individual properties.
  • asp-items=”Html.GetEnumSelectList<Department>()”: Populates the dropdown with enum values from the Department enum.
Success View

Create a new Razor view named Success.cshtml inside the Views/Employee folder and then copy and paste the following code.

@{
    ViewData["Title"] = "Success";
}

<h1>@ViewData["Title"]</h1>

<div class="alert alert-success" role="alert">
    <strong>Success!</strong> Employee added successfully.
</div>

<a asp-controller="Employee" asp-action="Create" class="btn btn-primary">Add Another Employee</a>
Testing the Application:

Now, run the application, navigate to the /Employee/Create URL, and submit the form without filling in any data. You will see the following error messages.

What are Validations?

Customizing Model Validation Error Message in ASP.NET Core MVC

By default, validation attributes provide generic error messages. For example, the Required Data Annotation attribute on the Name, Email, and Department properties displays the following default validation error messages.

  • The Name field is required.
  • The Email field is required.
  • The Department field is required.

We can customize these generic messages to offer a better user experience. For this, we need to use the ErrorMessage property of the Data Annotation Attributes. So, please modify the Employee Model class, as shown below, to display a user-friendly error message when the user submits the form without providing values for these fields.

using System.ComponentModel.DataAnnotations;
namespace DataAnnotationsDemo.Models
{
    // Represents an employee with validation rules.
    public class Employee
    {
        public int Id { get; set; }

        [Required(ErrorMessage = "Please enter the first name.")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Please enter the email address.")]
        public string Email { get; set; }

        [Required(ErrorMessage = "Please select a department.")]
        public Department? Department { get; set; }
    }
}

Each [Required] attribute now includes an ErrorMessage property that provides a user-friendly message when validation fails. With the above model changes, run the application, navigate to the /Employee/Create URL, and submit the form without filling in any data. You will see the following custom error messages as expected.

Customizing Model Validation Error Message in ASP.NET Core MVC

Applying Multiple Validation Attributes on a Single Model Property:

It is also possible in ASP.NET Core to apply multiple validation attributes on a single property. For example, we have only applied the Required Attribute with the Email Property. So, in this case, it will only check whether you are providing any value for the Email Field. It will not check whether the entered value is in the proper format. So, if you enter anything and submit the form, it will not give you any error message, as shown in the below image.

Applying Multiple Validation Attributes on a Single Model Property

We also want to apply the invalid format validation to the email field along with the required validation. To achieve this, we need to use either the EmailAddress Attribute or RegularExpression attribute along with the Required Attribute. So, modify the Employee class as follows.

using System.ComponentModel.DataAnnotations;
namespace DataAnnotationsDemo.Models
{
    public class Employee
    {
        public int Id { get; set; }

        [Required(ErrorMessage = "Please enter the first name.")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Please enter the email address.")]
        //[EmailAddress(ErrorMessage = "Please enter a valid email address.")]
        [RegularExpression(@"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", ErrorMessage = "Please enter a valid email address.")]
        public string Email { get; set; }

        [Required(ErrorMessage = "Please select a department.")]
        public Department? Department { get; set; }
    }
}

The Email property now has both [Required] and [EmailAddress] attributes, ensuring it is not only filled out but also in a proper format. Alternatively, you can use [RegularExpression] for more customized email validation, but [EmailAddress] suffices for standard scenarios.

With the above changes in place, run the application, navigate to the /Employee/Create URL, and submit the form by entering an invalid email address. You should get the appropriate custom error message, as shown in the below image.

Why do we Need Data Annotation Attributes in ASP.NET Core MVC for Validation?

Currently, Validation is performed on the server side, not on the client side. The Validation attributes in the ASP.NET Core MVC Framework provide client and server-side validation. Let us understand how to enable client-side validation in our ASP.NET Core MVC Application.

Enabling Client-Side Validation in ASP.NET Core MVC

While server-side validation is essential, enhancing user experience with Client-Side Validation ensures that users receive immediate feedback without waiting for a server response. ASP.NET Core MVC integrates with jQuery Validation and jQuery Unobtrusive Validation to provide client-side validation. To enable client-side validation in ASP.NET Core MVC Application, we need to include the following JavaScript libraries in our project:

  • jQuery: It provides core functionality for DOM manipulation and event handling, making it simpler to write complex client-side scripts that enhance user experience. Without this Library, jQuery will not work.
  • jQuery Validation: Plugin for client-side form validation. This plugin ensures that validation rules are enforced on the client side before the form data is sent to the server. This reduces the server load and provides immediate feedback to users.
  • jQuery Unobtrusive Validation: Bridges ASP.NET Core MVC’s validation attributes with the jQuery Validation plugin. It generates data-* attributes from model data annotation attributes to control the behavior of client-side validation without additional scripting.
Using CDNs:

For example, include them via CDNs in your _Layout.cshtml:

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<!-- jQuery Validation Plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.5/jquery.validate.min.js"></script>
    
<!-- jQuery Unobtrusive Validation -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.13/jquery.validate.unobtrusive.min.js"></script>
Using Local Files:

Alternatively, you can include these scripts locally in your _Layout.cshtml:

<!-- jQuery -->
<script src="~/lib/jquery/dist/jquery.min.js"></script>

<!-- jQuery Validation Plugin -->
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>

<!-- jQuery Unobtrusive Validation -->
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
Important Considerations:

Ensure that scripts are loaded in the correct order as follows:

  • jQuery
  • jQuery Validation
  • jQuery Unobtrusive Validation

This order is important because each subsequent script depends on the previous one. So, let us modify the _Layout.cshtml view with local JavaScript as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - DataAnnotationsDemo</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/DataAnnotationsDemo.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">DataAnnotationsDemo</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - DataAnnotationsDemo - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
   
    <!-- jQuery -->
    <script src="~/lib/jquery/dist/jquery.min.js"></script>

    <!-- jQuery Validation Plugin -->
    <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>

    <!-- jQuery Unobtrusive Validation -->
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

With the above changes, run the application and test the validation. This time, it will do client-side validation without making a server round trip, enhancing the user experience and reducing the load on the server.

Optimizing Script Inclusion with Partial Views

Including validation scripts globally in the layout can lead to unnecessary script downloads on pages that don’t require validation. You need to remember that we will not create forms or perform client-side validations on every page of our application. If we include the Validation JavaScript files inside our Layout files, they will be downloaded on every page where we use the layout file, even if we are not performing client-side validations. To optimize, we can use Partial Views for script inclusion.

Create a Partial View for Validation Scripts

Create a partial view named _ValidationScriptsPartial.cshtml under the Views/Shared folder and then copy and paste the following code. You can also observe that this file is already created by the framework when we create the ASP.NET Core Project using the Model View Controller template. We are not including the jQuery.js file because the jQuery.js file is required in all the pages, and hence, it is better to put that file inside the layout file.

<!-- jQuery Validation Plugin -->
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>

<!-- jQuery Unobtrusive Validation -->
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
Modify the Layout to Support Render Sections

Next, we must add a render section inside the layout file to scripts. So, modify the _Layout.cshtml file as follows to include a render section for scripts. By default, the Scripts section is created by the Framework inside the Layout file.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - DataAnnotationsDemo</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/DataAnnotationsDemo.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">DataAnnotationsDemo</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - DataAnnotationsDemo - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
   
    <!-- jQuery -->
    <script src="~/lib/jquery/dist/jquery.min.js"></script>

    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    <!-- Render Scripts Section -->
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Include Validation Scripts in Specific Views

In views that require client-side validation (e.g., Create.cshtml), include the partial view within a Scripts section. So, modify the Create.cshtml view as follows:

@model DataAnnotationsDemo.Models.Employee

@{
    ViewData["Title"] = "Create";
}

<h1>Create Employee</h1>

<!-- Employee Creation Form -->
<div class="row">
    <form asp-controller="Employee" asp-action="Create" method="post" class="mt-3">
        <!-- Validation Summary to display all validation errors -->
        <div asp-validation-summary="All" class="text-danger"></div>
        
        <!-- Name Field -->
        <div class="form-group row">
            <label asp-for="Name" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Name" class="form-control" placeholder="Enter your name" />
                <!-- Displays validation error for Name -->
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
        </div>

        <!-- Email Field -->
        <div class="form-group row">
            <label asp-for="Email" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Email" class="form-control" placeholder="Enter Your Email">
                <!-- Displays validation error for Email -->
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
        </div>

        <!-- Department Field -->
        <div class="form-group row">
            <label asp-for="Department" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <select asp-for="Department" class="form-select"
                        asp-items="Html.GetEnumSelectList<Department>()">
                    <option value="">Please Select</option> <!-- Placeholder option -->
                </select>
                <!-- Displays validation error for Department -->
                <span asp-validation-for="Department" class="text-danger"></span>
            </div>
        </div>

        <!-- Submit Button -->
        <div class="form-group row">
            <div class="col-sm-10 offset-sm-2">
                <button type="submit" class="btn btn-primary">Create</button>
            </div>
        </div>
    </form>
</div>
<!-- Include Validation Scripts -->
@section Scripts {
    @{
        await Html.RenderPartialAsync("_ValidationScriptsPartial");
    }
}

With this approach, only pages that require validation scripts will load, improving performance. After making these changes, run the application, and you will see that the client-side validation is working as expected.

Using HTML Helper to Provide Validation Message:

Instead of using asp-validation-summary and asp-validation-for tag helpers, which Microsoft also recommends, we can use HTML.ValidationSummary and Html.ValidationMessageFor helper methods to achieve the same. For a better understanding, please modify the Create.cshtml file as shown below to use HTML helper methods to display the error message.

@model DataAnnotationsDemo.Models.Employee

@{
    ViewData["Title"] = "Create";
}

<h1>Create Employee</h1>

<!-- Employee Creation Form -->
<div class="row">
    <form asp-controller="Employee" asp-action="Create" method="post" class="mt-3">
        <!-- Validation Summary to display all validation errors -->
        <div asp-validation-summary="All" class="text-danger"></div>
        
        <!-- Name Field -->
        <div class="form-group row">
            <label asp-for="Name" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Name" class="form-control" placeholder="Enter your name" />
                <!-- Displays validation error for Name -->
                <span class="text-danger">
                    @Html.ValidationMessageFor(x => x.Name)
                </span>
            </div>
        </div>

        <!-- Email Field -->
        <div class="form-group row">
            <label asp-for="Email" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Email" class="form-control" placeholder="Enter Your Email">
                <!-- Displays validation error for Email -->
                <span class="text-danger">
                    @Html.ValidationMessageFor(x => x.Email)
                </span>
            </div>
        </div>

        <!-- Department Field -->
        <div class="form-group row">
            <label asp-for="Department" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <select asp-for="Department" class="form-select"
                        asp-items="Html.GetEnumSelectList<Department>()">
                    <option value="">Please Select</option> <!-- Placeholder option -->
                </select>
                <!-- Displays validation error for Department -->
                <span class="text-danger">
                    @Html.ValidationMessageFor(x => x.Department)
                </span>
            </div>
        </div>

        <!-- Submit Button -->
        <div class="form-group row">
            <div class="col-sm-10 offset-sm-2">
                <button type="submit" class="btn btn-primary">Create</button>
            </div>
        </div>
    </form>
</div>
<!-- Include Validation Scripts -->
@section Scripts {
    @{
        await Html.RenderPartialAsync("_ValidationScriptsPartial");
    }
}
Common Validation Scenarios Encountered on Websites:

Web applications often encounter various validation scenarios. The following are some of the most common Validation Scenarios:

  • Required Fields: Ensures that necessary fields are not left empty. That is, mandatory fields must be filled.
  • Data Type Validation: Verifying that input data is of the correct type (e.g., numbers, dates).
  • Range Validation: Checking if numerical values fall within a specified range. For example, age should be between 18 and 60.
  • Format Validation: Checks for valid formats, such as email addresses, phone numbers, or postal codes.
  • Consistency Check: Verifying that related fields have consistent data. For instance, the “Confirm Password” field should match the “Password” field. Another example you can take when entering the credit card number is
  • Custom Business Rules: Certain validations might be unique depending on the application’s business logic. For example, a flight booking system might validate that the return date is after the departure date.
  • Blacklist Checks: Restricting inputs against known malicious or undesired values.
  • Whitelist Checks: Allowing only specific values or patterns, enhancing security.
  • Size Limit Checks: Ensuring data, especially uploaded files, do not exceed size limits.
  • CAPTCHAs: Validating that the user is human and not an automated bot.
Best Practices for Validation in ASP.NET Core MVC

Implementing validation effectively requires following the best practices to ensure security, performance, and a positive user experience.

  • Combine Client-Side and Server-Side Validation: The Client-side is for a better user experience, and the server-side is for security.
  • Consistent Validation Rules: Ensure validation logic is uniform across client and server to prevent discrepancies.
  • Clear Error Messages: Provide clear and informative error messages to guide the user through what went wrong and help them correct their input.
  • Avoid Loading Validation Scripts If Not Required: Load validation scripts only on necessary pages where the Validation is required to improve the application performance.
  • Minimize Data Exposure: Avoid exposing sensitive validation logic or error details that could help attackers.

Model validation is an integral part of building secure and user-friendly web applications. Using Data Annotations in ASP.NET Core MVC, we can efficiently enforce validation rules on models, providing immediate feedback to users and ensuring data integrity.

In the next article, I will discuss How to Perform Model Validations using Data Annotation Attributes in ASP.NET Core MVC Application with Examples. In this article, I try to explain Model Validations in ASP.NET Core MVC with Examples. I hope you enjoy this Model Validations in ASP.NET Core MVC article.

1 thought on “Model Validations in ASP.NET Core MVC”

  1. In case model state is not valid then how sure that it will go to index view in my case it is showing Signup.cshtml page not found??

Leave a Reply

Your email address will not be published. Required fields are marked *