Back to: ASP.NET Core Tutorials For Beginners and Professionals
Remote Validation in ASP.NET Core MVC
In this article, I will discuss How to Implement Remote Validations in ASP.NET Core MVC Applications with Real-Time Examples. Please read our previous article discussing Custom Data Annotation in ASP.NET Core MVC. At the end of this article, you will understand what Remote Validation is, why we need it, and how to implement Remote Validations in ASP.NET Core MVC applications.
What is Remote Validation in ASP.NET Core MVC Application?
Remote validation in ASP.NET Core MVC allows you to validate input on the server side without a full postback. This can be beneficial when you want to check if data is unique or meets certain criteria and provide instant feedback to the user before they submit the form.
For example, sometimes, to check whether a field value is valid, we may need to make a database call. A classic example of this is the Gmail user registration page. To register a user, we need a unique email. So, to check if the email is not taken already, we have to call the server and check the database table. RemoteAttribute is useful in situations like this.
Example: When a user provides an already existing email, the associated validation error message should be displayed immediately as shown below.
Let us understand how to implement remote validation in ASP.NET Core MVC step by step.
Create a Validation Action
First, create an action method in a controller that will be used to validate the input. So, create a RemoteValidationController controller and copy and paste the following code. In the below controller, we have created the IsEmailAvailable action method, which will validate whether an email is unique. In the below code, we check the Email against a list of hard-coded values, but in real-time, you need to check against the database table.
using DataAnnotationsDemo.Models; using Microsoft.AspNetCore.Mvc; namespace DataAnnotationsDemo.Controllers { public class RemoteValidationController : Controller { public List<User> Users; public RemoteValidationController() { Users = new List<User>() { new User(){UserID =1, FullName = "Pranaya Rout", Email="pranaya@example.com", Password ="12345"}, new User(){UserID =2, FullName = "Anurag Mohanty", Email="anurag@example.com", Password ="56789"}, new User(){UserID =3, FullName = "Hina Sharma", Email="hina@example.com", Password ="112233"} }; } [HttpPost] public JsonResult IsEmailAvailable(string Email) { //Check the Email Id in the Database return Json(!Users.Any(x => x.Email == Email)); } } }
IsEmailAvailable(string Email): An AJAX request is issued to this method. If this method returns true, validation succeeds, validation fails, and the form is prevented from being submitted. The parameter name Email must match the field name on the view. If they don’t match, the model binder will not be able to bind the value with the parameter, and validation may not work as expected.
Apply Remote Attribute:
Apply the Remote attribute to the property you want to validate. To validate the Email ID, create a model class named User.cs and copy and paste the following code. As you can see, we have applied the Remote Data Annotation Attribute with the Email Property and specified the controller, action, method type, and custom error message.
using Microsoft.AspNetCore.Mvc; using System.ComponentModel.DataAnnotations; namespace DataAnnotationsDemo.Models { public class User { public int UserID { get; set; } public string FullName { get; set; } [Remote("IsEmailAvailable", "RemoteValidation", HttpMethod = "POST", ErrorMessage = "Email ID already in use.")] public string Email { get; set; } [DataType(DataType.Password)] public string Password { get; set; } } }
In the above code, we have defined a few properties of the Remote attribute to work on remote validation properly. Let’s know them in brief.
- IsEmailAvailable: This is the JsonResult action method that checks the details from the database and returns true or false.
- RemoteValidation: This is the Controller name; inside that, the IsEmailAvailable JsonResult method is defined to check the details from the database.
- HttpMethod: This is the HttpMethod type called on the Remote attribute, e.g., GET, PUT, POST. This is optional to define.
- ErrorMessage: This is used to show the message on the client side.
Ensure Client-Side Scripts are Included
To enable client-side validation (which includes remote validation), you need to include jQuery and jQuery Validate libraries:
You must include jQuery, jQuery Validation, and jQuery Unobtrusive Validation in your project. These can be added via CDNs or local files. For example, include them via CDNs in your _Layout.cshtml:
<!-- jQuery --> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> <!-- jQuery Validation Plugin --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.2/jquery.validate.min.js"></script> <!-- jQuery Unobtrusive Validation (to bridge ASP.NET Core MVC validation with jQuery Validate) --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
Please add the following files in your _Layout.cshtml to enable client-side validation using local files. The order is also important; please include them in the following order.
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script> <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
Ensure Your Form is Set Up Properly:
Next, modify the Home Controller as shown below.
using DataAnnotationsDemo.Models; using Microsoft.AspNetCore.Mvc; namespace DataAnnotationsDemo.Controllers { public class HomeController : Controller { public ActionResult Create() { return View(); } [HttpPost] public ActionResult Create(User user) { //Check if the Model State is Valid if (ModelState.IsValid) { //Save the Data into the Database //Redirect to a Different View return RedirectToAction("Successful"); } //Return to the same View and Display Model Validation error return View(user); } public string Successful() { return "Employee Addedd Successfully"; } } }
Next, modify the Create.cshtml view of the Home Controller as shown below.
@model DataAnnotationsDemo.Models.User @{ ViewData["Title"] = "Create"; } <h1>Create User</h1> <div class="row"> <form asp-controller="Home" asp-action="Create" method="post" class="mt-3"> <div asp-validation-summary="All" class="text-danger"></div> <div class="form-group row"> <label asp-for="FullName" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="FullName" class="form-control" placeholder="Enter Your Name"> <span asp-validation-for="FullName" class="text-danger"></span> </div> </div> <br/> <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 User Name"> <span asp-validation-for="Email" class="text-danger"></span> </div> </div> <br /> <div class="form-group row"> <label asp-for="Password" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="Password" class="form-control" placeholder="Enter Your Password"> <span asp-validation-for="Password" class="text-danger"></span> </div> </div> <br /> <div class="form-group row"> <div class="col-sm-10"> <button type="submit" class="btn btn-primary">Create</button> </div> </div> </form> </div>
Run the application and see if everything is working as expected. The remote attribute only works when JavaScript is enabled. If the end-user disables JavaScript on his/her machine, the validation does not work.
Remote validation in ASP.NET Core MVC when JavaScript is Disabled:
The Remote attribute only works when JavaScript is enabled. If the end-user disables JavaScript on his/her machine, the validation does not work. RemoteAttribute requires JavaScript to make an asynchronous AJAX call to the server-side validation method. As a result, the user can submit the form, bypassing the validation in place. This is why it is always important to have server-side validation.
So, when JavaScript is disabled in the browser, client-side validation, including remote validation, won’t work. In such cases, the traditional server-side postback approach must handle validation. To make server-side validation work when JavaScript is disabled, there are 2 ways
- Add model validation error dynamically in the controller action method
- Create a custom remote attribute and override IsValid() method
Add Model Validation Error Dynamically in the Controller Action Method:
Instead of relying on AJAX to validate a single field, we will need to do a full-form submission (postback) to check for validation. When processing the form post in the controller, perform the remote validation manually. Modify the Create action method of the Home Controller that is decorated with the [HttpPost] attribute as shown below.
using DataAnnotationsDemo.Models; using Microsoft.AspNetCore.Mvc; namespace DataAnnotationsDemo.Controllers { public class HomeController : Controller { public List<User> Users; public HomeController() { Users = new List<User>() { new User(){UserID =1, FullName = "Pranaya Rout", Email="pranaya@example.com", Password ="12345"}, new User(){UserID =2, FullName = "Anurag Mohanty", Email="anurag@example.com", Password ="56789"}, new User(){UserID =3, FullName = "Hina Sharma", Email="hina@example.com", Password ="112233"} }; } public ActionResult Create() { return View(); } [HttpPost] public ActionResult Create(User user) { // Check for email uniqueness, for example if (Users.Any(u => u.Email == user.Email)) { ModelState.AddModelError("Email", $"Email {user.Email} is already in use."); } //Check if the Model State is Valid if (ModelState.IsValid) { //Save the Data into the Database //Redirect to a Different View return RedirectToAction("Successful"); } //Return to the same View and Display Model Validation error return View(user); } public string Successful() { return "Employee Addedd Successfully"; } } }
Now, disable JavaScript in the browser and test your application. Notice that we don’t get client-side validation, but when we submit the form, server-side validation still prevents the user from submitting the form if there are validation errors.
However, delegating the responsibility of performing validation to a controller action method violates the separation of concerns within MVC. Ideally, all validation logic should be in the Model. Using validation attributes in models should be the preferred method for validation.
Creating a Custom Remote Attribute:
Creating a custom data annotation attribute for remote validation in ASP.NET Core MVC allows you to encapsulate the remote validation logic within the attribute, making it reusable across different models. Let us understand how we can implement this in ASP.NET Core MVC. So, create a class file named RemoteValidationAttribute.cs and copy and paste the following code.
using System; using System.ComponentModel.DataAnnotations; namespace DataAnnotationsDemo.Models { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class RemoteValidationAttribute : ValidationAttribute { public override bool IsValid(object value) { //Hardcoding the Data List<User> Users = new List<User>() { new User(){UserID =1, FullName = "Pranaya Rout", Email="pranaya@example.com", Password ="12345"}, new User(){UserID =2, FullName = "Anurag Mohanty", Email="anurag@example.com", Password ="56789"}, new User(){UserID =3, FullName = "Hina Sharma", Email="hina@example.com", Password ="112233"} }; if (value is string email) { return !Users.Any(x => x.Email == email); } return false; } } }
Apply the Custom Attribute to a Model:
using System.ComponentModel.DataAnnotations; namespace DataAnnotationsDemo.Models { public class User { public int UserID { get; set; } public string FullName { get; set; } [RemoteValidation(ErrorMessage = "Email ID already in use.")] public string Email { get; set; } [DataType(DataType.Password)] public string Password { get; set; } } }
Disable JavaScript in the browser, and test your application. Notice that we don’t get client-side validation, but when you submit the form, server-side validation still prevents the user from submitting the form if there are validation errors.
Real-time Examples Remote Validations using Data Annotation in ASP.NET Core MVC
Remote validations in ASP.NET Core MVC are useful for checking data against a database or external service without submitting the entire form. Here are some real-world examples where remote validation can be useful:
Checking Username Availability:
When users register on a platform, you can use remote validation to check if the username they’ve entered is already taken.
Model:
{ [Remote("IsUsernameAvailable", "Account", ErrorMessage = "Username is already taken.")] public string Username { get; set; } // ... other properties like Password, Email, etc. }
Controller:
public class AccountController : Controller { private readonly MyDbContext _context; public AccountController(MyDbContext context) { _context = context; } public IActionResult IsUsernameAvailable(string username) { bool isAvailable = !_context.Users.Any(u => u.Username == username); return Json(isAvailable); } }
Validating Email Domain:
In some scenarios, especially for business apps, you might only want to allow registration or sign-up from specific email domains (e.g., from your organization).
Model:
public class BusinessSignUpViewModel { [Remote("IsValidDomain", "Business", ErrorMessage = "Only emails from specific domains are allowed.")] public string Email { get; set; } }
Controller:
public class BusinessController : Controller { public IActionResult IsValidDomain(string email) { var allowedDomains = new List<string> { "mybusiness.com", "partner.com" }; string domain = email.Split('@').Last(); bool isValidDomain = allowedDomains.Contains(domain); return Json(isValidDomain); } }
Product SKU/Code Validation:
In an e-commerce platform, the SKU or product code should be unique when adding products. Remote validation can help ensure that the code entered hasn’t been used.
Model:
public class AddProductViewModel { [Remote("IsProductCodeUnique", "Products", ErrorMessage = "This product code is already in use.")] public string ProductCode { get; set; } // ... other properties like Name, Price, etc. }
Controller:
public class ProductsController : Controller { private readonly MyDbContext _context; public ProductsController(MyDbContext context) { _context = context; } public IActionResult IsProductCodeUnique(string productCode) { bool isUnique = !_context.Products.Any(p => p.ProductCode == productCode); return Json(isUnique); } }
These are just a few examples, but remote validation can be used in numerous scenarios where real-time validation against a database or external service is required. However, always remember that while remote validation provides a better user experience, you should still validate the data server-side when the form is submitted as an added layer of security and data integrity.
In the next article, I will discuss Blacklist and Whitelist Checks using Data Annotation in ASP.NET Core MVC Application. In this article, I try to explain Remote Validation in ASP.NET Core MVC Application with examples. I hope you enjoy this Remote Validation in ASP.NET Core MVC article.
About the Author: Pranaya Rout
Pranaya Rout has published more than 3,000 articles in his 11-year career. Pranaya Rout has very good experience with Microsoft Technologies, Including C#, VB, ASP.NET MVC, ASP.NET Web API, EF, EF Core, ADO.NET, LINQ, SQL Server, MYSQL, Oracle, ASP.NET Core, Cloud Computing, Microservices, Design Patterns and still learning new technologies.