21
NovASP.NET Core MVC Model Validation
ASP.NET Core MVC Model Validation: An Overview
When we develop any type of web-based or desktop-based application, one key part of development is Data Validation or Form Validation. These validations ensure that the user fills in the correct data into the application so that we can process that data and save it for future use. Normally, users always fill out the form with the necessary information and submit it.
But, sometimes the user makes some mistakes. In this case, form validation is required to ensure that the user always provides the required information in the proper format which is required for the successful submission of the form.
In this ASP.NET Core tutorial, we will discuss different types of form validations. To make things easier for you, ScholarHat brings comprehensive skill-oriented ASP.NET Core Online Trainingto the nitty-gritty of ASP.NET.
Read More: Top 50 ASP.NET Core Interview Questions and Answers for 2024
What is Model Validation in ASP.NET Core?
When we visit any popular website for registration purposes, we notice that the site gives us some error message or warning message when we do not put properly formatted data in the form's controls. Normally, we receive the message as below –
- The field value is required. We can’t leave the field blank.
- Please enter your data in the correct format in case of phone number, date of birth, etc.
- Please provide a valid email address.
- Your password does not match the format like uppercase, one symbol, and one number.
This type of message is known as form validation. When a user fills the data in the forms, web applications validate that data whether it is correct or not. If it is correct, the application sends those data to the server for saving into the database. If it is not in the correct format, then it throws error messages providing information about what corrections need to be done by the user. These validations are important for any developer due to the following reasons –
- We always want to receive the correct data in the correct format from the user.
- We want to protect the user data by forcing users to provide some confidential information in a specified format.
- Also, with the help of form validations, we can protect ourselves from malicious uses of our applications.
Read More: Understanding ASP.NET Core Tag Helpers
Validation Types
Forcing users to provide properly formatted and necessary information for any type of form is the main objective of the form validations. Normally, we can perform form validation in two ways – either implement in the server-side code i.e. Server-Side Validation or implement these in the client-side i.e. Client-Side validation. In the below section, we discuss both the validation types.
1. Server Side Validation
Here, information filled in by the users is sent to the server and validated using the server-side language i.e. Asp.Net Core. In this process, if the data is not validated, a response along with a proper error message is sent back to the client where these messages are shown to the user to be rectified. This type of validation is always secure because if the user disabled the scripting language in the browser then also it will work. At the same time, it can’t be bypassed by the user very easily.
One problematic concern is that here the user cannot know what mistakes have been made until the user completes the data entry and submits the data. Since these processes always communicate with the server, that’s why it is a little bit slow process for the output or error message.
In Asp.Net Core, the best way to perform the server-side validation is using Model Validation. Likely, Microsoft provides us with the abstract validation layer as validation attributes which contains validation code. Therefore, these approaches always reduce the amount of code writing for us. The validation attribute is one of the ways to implement or configure model validations in the model class property. These validations can work like constraints such as assigning maximum length or required fields.
Other validation types can implement some common business rules on data like – Email Address, Phone, Range, etc. The validation attribute always enforces some logical business rule in a simple and easy-to-use way. Below is an Employee Model for an application in which Validation attributes like required, and length have been implemented.
public class Employee
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string EmployeeName { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime JoinDate { get; set; }
[Required]
[StringLength(100)]
public string Designation { get; set; }
[Range(0, 999.99)]
public decimal Salary { get; set; }
[Required]
public Gender Gender { get; set; }
public string Address { get; set; }
}
From the above model class, it is clear that we just need to add the related rule in the model class properties to force the user to provide proper data. In the below table, there are some popular inbuild available validation attributes in the Asp.Net Core –
Asp.Net Core provides support against all the validation attributes that are inherited from the ValidationAttribute class. Also, we can create a custom server-side validation attribute by implementing the interface named IValidationObjects.
In Asp.Net Core, the Model state always returns validation errors in a normal HTML format in the interface. This will continue the validation process against the form field until the total error number reaches its maximum limits (200 is by default). But we can configure this maximum error number in the ConfigureServices() in the Startup.cs class.
services.AddMvc(options => options.MaxModelValidationErrors = 50);
2. Client Side Validation
Server-side validation is the most successful and secure validation process. But sometimes, we need to implement client-side validation for a better user experience. Normally, this type of validation is done by the scripting languages on the client side. By using this type of validation, we can implement much more responsive and visually rich validation of the user's input data on the client side. The best thing about this type of validation is that the form submit method is not executed in this case if validation fails.
This means, that if we implement client-side validation in our application, then the server-side method or process will be invoked only when client-side validation has been passed successfully. Otherwise, it will not invoke the server-side code so there is no load in the server-side. So, that’s why Client-Side validation always performs faster execution of error and it increases the performance of the applications.
However, the main disadvantage of this type of validation is that it depends on JavaScript. So, if the user disabled the JavaScript in the browser, the validation process can be bypassed and the server-side method can be invoked with the wrong data. And, if we do not implement the same client-side validation on the server side, then there is a high probability that the system can accept the wrong or incorrect data. For this reason, it is always better to implement the same validation rule or method on both sides i.e. Server-side and client.
So, to implement the Client-side validation, we need to add the proper JavaScript script reference in the UI for this purpose as below –
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.2.0.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.16.0/jquery.validate.min.js"></script>
<script
src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.mi
n.js"></script>
In the above script reference, jQuery Unobtrusive Validation is one of the custom front-end libraries provided by Microsoft based on the most popular and well-known scripting library jQuery validate plugin. This front end is responsible for implementing the same validation logic on both sides of the application.
We can generate any type of custom data attribute for both the server and client side with the help of Asp.Net Core. For custom data attributes, the JQuery Unobtrusive library simply transfers the server-side validation logic to the client side. We can display the validation error message on the client side with the help of related Tag Helpers as shown below –
<div class="form-group">
<label asp-for="JoineDate" class="col-md-4 control-label"></label>
<div class="col-md-10">
<input asp-for=" JoineDate" class="form-control" />
<span asp-validation-for="JoineDate" class="text-danger"></span>
</div>
</div>
In the above code sample, data attribute validation is used only for the JoineDate Property. If you do not fill this field value, then the data-val-required attribute always contains an error message which we provide the server side. In this way, the jQuery Unobtrusive library passes the validation to the client side as required, which will be displayed in the span tag or an alert window.
<form action="/Employee/Create" method="post">
<div class="form-horizontal">
<h4> Employee Information</h4>
<div class="text-danger"></div>
<div class="form-group">
<label class="col-md-2 control-label" for="JoineDate"> JoineDate </label>
<div class="col-md-10">
<input class="form-control" type="datetime"
data-val="true" data-val-required="The Date of Join field is required."
id="JoineDate " name="JoineDate" value="" />
<span class="text-danger field-validation-valid"
data-valmsg-for="JoineDate" data-valmsg-replace="true"></span>
</div>
</div>
</div>
</form>
Custom Server Side Validations and Client Side Validations
So, both Server-side and Client-Side validation attributes work perfectly for most of the cases and also fulfill the requirement related to the validation required. But, still, there are some situations, when we need to specify some custom validation related to the business for that model class. In this case, custom validation is one of the best processes to perform the validations. We can implement the custom validation either on the Server-Side or Client-Side very easily.
These custom validations might not be the same as the validation attributes required on the server side. To do these, we need to inherit ValidationAttribute in our class and then we need to override the method called IsValid(). It always accepts two parameters – the first parameter is an object type called value and the second one is the object of ValidationContext on the requirement also implemented in validationContext.
In the below example, we will demonstrate the default custom validation format for the service side.
public class EmployeeAttribute : ValidationAttribute, IClientModelValidator
{
private int _year;
public EmployeeAttribute(int Year)
{
_year = Year;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Employee employee = (Movie)validationContext.ObjectInstance;
if (employee.Gender == Gender.Male && employee.ReleaseDate.Year> _year)
{
return new ValidationResult(GetErrorMessage());
}
return ValidationResult.Success;
}
In the above example, the employee variable acts as an Employee object, which generates the IsValid() of the EmployeeAttribute class. Success code has been returned after the execution of validation. Similarly, an error result as a ValidationResult has been returned in case of validation failure.
private string GetErrorMessage()
{
return $"Employee Must the have the Joining Date";
}
Also, the same validation rule can be implemented with the help of validate() by using the IValidatableObject interface. Custom validation attributes main objective is to perform checks against the individual properties of the model class. In this case, IValidatableObject can be implemented for class-level validations.
public IEnumerable<ValidationResult>ValidateEmployee(ValidationContext validationContext)
{
if (Gender == Employee.Male && JoinDate.Year > _year)
{
yield return new ValidationResult(
$" Employee Must the have the Joining Date.",
new[] { "ReleaseDate" });
}
}
So, we can also add the custom validation on the client side. For that, we need to use the jQuery Unobtrusive validation process to pass the server-side validation to the client side.
var form = document.getElementById("my-form");
form.insertAdjacentHTML("beforeend", newInputHTML);
$(form).removeData("validator").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
We may also create client-side custom validation logic for our custom attribute and then unobtrusive validation create a jQuery adapter which will execute the custom validation logic in the client machine for the part of the automatic validation process. The first step for this is to add the data attributes by using the IClientModelValidator interface.
public void AddEmployeeValidation(ClientModelValidationContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
MergeAttribute(context.Attributes, "data-employee", "true");
MergeAttribute(context.Attributes, "data-employee", GetErrorMessage());
var age = _year.ToString(CultureInfo.InvariantCulture);
MergeAttribute(context.Attributes, "data- employee -year", age);
}
So, these are the custom attributes that can be used in the HTML part when we use that. Now the sample HTML which can implement the above custom validation attributes as
<input class="form-control" type="datetime"
data-val="true"
data-val-employee ="Employee Date of Birth Must be Before year 2000."
data-val-employee -year="2000"
data-val-required="The Joining Date field is required."
id="JoinDate" name=" JoinDate " value="" />
Displaying Model Validation Errors in “asp-validation-summary” Tag Helper
To display model validation errors in the asp-validation-summary tag helper in ASP.NET Core, you need to ensure that your view is set up to show validation errors and that your controller returns validation errors when necessary.
- Configure Model Validation in Controller
In your controller action method, make sure you are validating the model using the ModelState.IsValid property. If the model is not valid, add model errors to the ModelState dictionary using the ModelState.AddModelError method.
Example
[HttpPost] public IActionResult Create(MyModel model) { if (!ModelState.IsValid) { // Add model errors if validation fails foreach (var error in ModelState.Values.SelectMany(v => v.Errors)) { ModelState.AddModelError("", error.ErrorMessage); } return View(model); } // Process valid model and return the appropriate response }
- Display Validation Errors in View
In your view, use the asp-validation-summary tag helper to display validation errors.
Example
<div class="validation-summary-errors"> <asp-validation-summary></asp-validation-summary> </div>
- Include Validation Tag Helpers in the Form
Ensure your form includes validation tag helpers for each input element to display field-specific validation errors.
Example
<form asp-action="Create" method="post"> <div class="form-group"> <label asp-for="Name"></label> <input asp-for="Name" class="form-control" /> <span asp-validation-for="Name" class="text-danger"></span> </div> <!-- Other input elements and validation tag helpers --> <button type="submit" class="btn btn-primary">Submit</button> </form>
Displaying Individual Model Validation Error Messages in ASP.NET CORE MVC
For this, we can use the asp-validation-for tag helper along with appropriate styling.
- Configure Model Validation in Controller
Ensure that your controller action method checks the ModelState.IsValid property and adds model errors to the ModelState dictionary as needed.
Example
[HttpPost] public IActionResult Create(MyModel model) { if (!ModelState.IsValid) { return View(model); } // Process valid model and return appropriate response }
- Display Validation Error Messages in View
In your view, use the asp-validation-for tag helper to display validation error messages for individual model properties.
Example
<div class="form-group"> <label asp-for="Name"></label> <input asp-for="Name" class="form-control" /> <span asp-validation-for="Name" class="text-danger"></span> </div>
- Styling
You can style the error messages using CSS to make them visually distinct from other content on the page.
Example
.text-danger { color: red; }
Model-Level Error Messages
For this, you can add error messages to the ModelState dictionary with an empty key in your controller.
- Configure Model Validation in Controller
In your controller action method, add model-level error messages to the ModelState dictionary using the empty key.
Example
[HttpPost] public IActionResult Create(MyModel model) { if (/* Some condition for model validation */) { ModelState.AddModelError("", "Model-level error message"); return View(model); } // Process valid model and return appropriate response }
- Display Model-Level Error Message in View
In your view, use the asp-validation-summary tag helper to display model-level error messages.
Example
<div class="validation-summary-errors"> <asp-validation-summary></asp-validation-summary> </div>
With these configurations in place, the model-level error message will be displayed in the asp-validation-summary tag helper at the top of the form.
Customizing Model Validation Behavior
For this, you can use data annotations, fluent API, or custom validation attributes to define validation rules for model properties.
- Data Annotations
Decorate model properties with data annotation attributes to specify validation rules.
Example
public class MyModel { [Required(ErrorMessage = "The Name field is required.")] public string Name { get; set; } [Range(18, 100, ErrorMessage = "The Age must be between 18 and 100.")] public int Age { get; set; } }
- Fluent API
Use the fluent API provided by ASP.NET Core's IValidatableObject interface to define custom validation logic for model objects. Implement the Validate method to perform custom validation checks and return validation results.
Example
public class MyModel : IValidatableObject { public string Name { get; set; } public IEnumerable Validate(ValidationContext validationContext) { if (string.IsNullOrEmpty(Name)) { yield return new ValidationResult("The Name field is required.", new[] { nameof(Name) }); } } }
- Custom Validation Attributes
Create custom validation attributes by deriving from the ValidationAttribute class and overriding the IsValid method. Implement custom validation logic inside the IsValid method and apply the custom attribute to model properties.
Example
public class CustomValidationAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (/* Custom validation logic */) { return ValidationResult.Success; } else { return new ValidationResult("Custom validation failed."); } } } public class MyModel { [CustomValidation] public string SomeProperty { get; set; } }
Extending Built-in Validation Attributes
For this, you can create custom validation attributes that inherit from existing validation attribute classes and override their behavior as needed.
- Create a Custom Validation Attribute
Define a new custom validation attribute class that inherits from the built-in validation attribute you want to extend. Override its behavior to provide additional validation logic or customize error messages.
Example
public class CustomRequiredAttribute : RequiredAttribute { public override bool IsValid(object value) { // Additional validation logic here return base.IsValid(value); } public override string FormatErrorMessage(string name) { return $"The {name} field is required."; } }
- Apply Custom Attribute to Model Properties
Apply the custom validation attribute to model properties in your application where you want to use the extended validation behavior.
Example
public class MyModel { [CustomRequired] public string Name { get; set; } }
Creating Custom Validation Attributes
This allows you to define custom validation rules that can be applied to model properties.
- Create Custom Validation Attribute Class
Define a new class that inherits from the ValidationAttribute base class. Override the IsValid method to implement your custom validation logic.
Example
using System; using System.ComponentModel.DataAnnotations; public class CustomDateRangeAttribute : ValidationAttribute { private readonly DateTime _minDate; private readonly DateTime _maxDate; public CustomDateRangeAttribute(string minDate, string maxDate) { _minDate = DateTime.Parse(minDate); _maxDate = DateTime.Parse(maxDate); } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (value != null) { DateTime dateValue = (DateTime)value; if (dateValue < _minDate || dateValue > _maxDate) { return new ValidationResult($"The field {validationContext.DisplayName} must be between {_minDate.ToShortDateString()} and {_maxDate.ToShortDateString()}."); } } return ValidationResult.Success; } }
- Apply Custom Attribute to Model Properties
Apply your custom validation attribute to model properties where you want to enforce the custom validation rule.
Example
public class MyModel { [CustomDateRange("2022-01-01", "2023-12-31")] public DateTime SomeDate { get; set; } }
- Usage in Views
Use the asp-validation-for tag helper or other validation helpers in your views to display validation error messages.
Example
<div class="form-group"> <label asp-for="SomeDate"></label> <input asp-for="SomeDate" class="form-control" /> <span asp-validation-for="SomeDate" class="text-danger"></span> </div>
So here, we have created a custom validation attribute CustomDateRangeAttribute that validates if a date falls within a specified range.
Read More: What is an ASP.NET Core Developer? Skills to become ASP.NET Core Developer
Implementing Custom Validation Logic
To implement custom validation logic in ASP.NET Core MVC, you can create custom validation attributes or use the IValidatableObject interface to define validation rules for your model.
- Using Custom Validation Attributes
Create a custom validation attribute by deriving from the ValidationAttribute class and overriding the IsValid method to implement your validation logic.
Example
using System; using System.ComponentModel.DataAnnotations; public class CustomValidationAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // Your custom validation logic here if (/* validation condition */) { return ValidationResult.Success; } else { return new ValidationResult("Custom validation error message."); } } } Apply the custom validation attribute to model properties where you want to enforce the custom validation rule. public class MyModel { [CustomValidation] public string SomeProperty { get; set; } }
- Using IValidatableObject Interface
Implement the IValidatableObject interface on your model class and define the Validate method to perform custom validation logic.
Example
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; public class MyModel : IValidatableObject { public string SomeProperty { get; set; } public IEnumerable Validate(ValidationContext validationContext) { // Your custom validation logic here if (/* validation condition */) { yield return ValidationResult.Success; } else { yield return new ValidationResult("Custom validation error message.", new[] { nameof(SomeProperty) }); } } }
Read More: Salary Offered to ASP.NET Developers
Summary
So, in this article, we discussed the concept of Form Validation in ASP.NET Core, including Server-Side Validations and Client-Side Validations. Also, we explored how to create custom validation on the server side and client side. For more in-depth knowledge, consider our ASP.NETCore Certification Course.
FAQs
Take our Aspnet skill challenge to evaluate yourself!
In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.