Skip to main content

Back-End Development

Remote validation in ASP.NET MVC without using jQuery

They've Got The Answers You're Looking For

In this blog, we will implement remote validation by making an ajax call to the server without using jQuery; we will achieve this using vanilla JavaScript.

What is the purpose of remote validation?

Here’s an explanation: Often, user inputs must be checked against a database to see if it already exists. We need to validate the input on the client side. We must achieve this without posting the entire form to the server. In such a scenario, a server call is necessary to confirm the uniqueness of the entered data. A username, for example, must be unique when creating a new user.

Remote Validation

ASP.NET MVC 3 provides the mechanism for performing remote validation. ASP.NET MVC’s remote validation depends heavily on the jQuery and jQuery.Validate libraries. Remote validation makes an ajax call to the server using jQuery.

Remote validation

 

Let’s start with model.

Here’s my user model having Id, Username, and Password properties.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
namespace ASP.Net_MVC.Models
{
[Table("Users")]
publicclass User
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
publicint Id {get; set; }
[Required(ErrorMessage = "This username is required.")]
publicstring UserName {get; set; }
[Required(ErrorMessage = "This password is required.")]
publicstring Password {get; set; }
}
}
namespace ASP.Net_MVC.Models { [Table("Users")] public class User { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] [Key] public int Id { get; set; } [Required(ErrorMessage = "This username is required.")] public string UserName { get; set; } [Required(ErrorMessage = "This password is required.")] public string Password { get; set; } } }
namespace ASP.Net_MVC.Models
{
   [Table("Users")]
    public class User

    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "This username is required.")]
        public string UserName { get; set; }

        [Required(ErrorMessage = "This password is required.")]
        public string Password { get; set; }
    }
}

CheckExistingUser action method is called when a user clicks a create button.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
namespace ASP.Net_MVC.Controllers
{
publicclass UserController : Controller
{
EmployeeContext _userService = newEmployeeContext();
// GET: User
public ActionResult Create()
{
returnView();
}
[HttpPost]
public ActionResult Create(User user)
{
if(ModelState.IsValid)
{
_userService.Users.Add(user);
_userService.SaveChanges();
returnRedirectToAction("Index");
}
returnView(user);
}
[AcceptVerbs("GET", "POST")]
public ActionResult CheckExistingUser(string userName)
{
if(!_userService.Users.Any(u => u.UserName == userName))
{
returnHttpNotFound();
}
returnnewHttpStatusCodeResult(200, $"A user {userName} already exists.");
}
namespace ASP.Net_MVC.Controllers { public class UserController : Controller { EmployeeContext _userService = new EmployeeContext(); // GET: User public ActionResult Create() { return View(); } [HttpPost] public ActionResult Create(User user) { if (ModelState.IsValid) { _userService.Users.Add(user); _userService.SaveChanges(); return RedirectToAction("Index"); } return View(user); } [AcceptVerbs("GET", "POST")] public ActionResult CheckExistingUser(string userName) { if (!_userService.Users.Any(u => u.UserName == userName)) { return HttpNotFound(); } return new HttpStatusCodeResult(200, $"A user {userName} already exists."); }
namespace ASP.Net_MVC.Controllers
{
    public class UserController : Controller
    {
        EmployeeContext _userService = new EmployeeContext();

        // GET: User
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(User user)
        {

                if (ModelState.IsValid)
                {
                    _userService.Users.Add(user);
                    _userService.SaveChanges();
                    return RedirectToAction("Index");
                }
            return View(user);
        }

        [AcceptVerbs("GET", "POST")]
        public ActionResult CheckExistingUser(string userName)
        {
            if (!_userService.Users.Any(u => u.UserName == userName))
            {
                return HttpNotFound();
            }

            return new HttpStatusCodeResult(200, $"A user {userName} already exists.");
        }

Create.cshtml (View)

On form submission, JavaScript onsubmit event gets called, which in turn calls a JavaScript function validateForm(). We are embedding a URL to an action method by specifying the action and controller names in the Url.Action method().

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@model ASP.Net_MVC.Models.User
@{
ViewBag.Title = "Create User";
}
<formasp-controller="User"asp-action="Create"id="form-submit"method="post"
onsubmit="return validateForm('@Url.Action("CheckExistingUser","User", null)', event)">
@Html.AntiForgeryToken()
<divclass="form-horizontal">
<h4>Create User</h4>
<hr/>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<divclass="form-group">
@Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
</div>
</div>
<divclass="form-group">
@Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
</div>
</div>
<divclass="error-div">
<labelid="errormessage"class="text-danger"></label>
</div>
<divclass="form-group">
<divclass="col-md-offset-2 col-md-10">
<inputtype="submit"value="Create"class="btn btn-default"/>
</div>
</div>
</div>
</form>
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@model ASP.Net_MVC.Models.User @{ ViewBag.Title = "Create User"; } <form asp-controller="User" asp-action="Create" id="form-submit" method="post" onsubmit="return validateForm('@Url.Action("CheckExistingUser","User", null)', event)"> @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Create User</h4> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) </div> </div> <div class="error-div"> <label id="errormessage" class="text-danger"></label> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div> </form> <div> @Html.ActionLink("Back to List", "Index") </div>
@model ASP.Net_MVC.Models.User

@{
    ViewBag.Title = "Create User";
}


<form asp-controller="User" asp-action="Create" id="form-submit" method="post" 
      onsubmit="return validateForm('@Url.Action("CheckExistingUser","User", null)', event)">

    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Create User</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="error-div">
            <label id="errormessage" class="text-danger"></label>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
</form>

    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>

JavaScript function to validate user

In the JavaScript validateForm() function, we split the URL and get the action method. We are splitting the URL as it can be reused for other action methods. We could get other DOM elements specific to each action method and reuse the same ajax call to send the fields to the action method and check for data uniqueness. From the controller action method, we receive a response, and based on that, we either display the validation error message to the user or submit the form.

If this method returns response code 404 NotFound, the username does not exist, and the form gets submitted; otherwise, the method returns response code 200 OK, a user already exists. The submitted form calls the create method, which adds the user to the database.

Note: The parameter name (userName) must match the parameter name in the appended query string of the URL in JavaScript.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
functionvalidateForm(url, event){
event.preventDefault();
let splits = url.split('/');
let action = splits[splits.length - 1];
if(action.includes("CheckExistingUser")){
console.log(action);
let userName = document.getElementById("UserName").value
url += `?userName=${userName}`
}
var xhttp = newXMLHttpRequest();
xhttp.open("GET", url, true);
xhttp.send();
xhttp.onreadystatechange = function(event){
if(this.readyState == 4&&this.status == 200){
document.getElementById("errormessage").innerHTML = this.statusText;
}
elseif(this.readyState == 4&&this.status == 404){
document.querySelector("#form-submit").submit();
}
};
}
function validateForm(url, event) { event.preventDefault(); let splits = url.split('/'); let action = splits[splits.length - 1]; if (action.includes("CheckExistingUser")) { console.log(action); let userName = document.getElementById("UserName").value url += `?userName=${userName}` } var xhttp = new XMLHttpRequest(); xhttp.open("GET", url, true); xhttp.send(); xhttp.onreadystatechange = function (event) { if (this.readyState == 4 && this.status == 200) { document.getElementById("errormessage").innerHTML = this.statusText; } else if (this.readyState == 4 && this.status == 404) { document.querySelector("#form-submit").submit(); } }; }
function validateForm(url, event) {
    event.preventDefault();

    let splits = url.split('/');
    let action = splits[splits.length - 1];

    if (action.includes("CheckExistingUser")) {
        console.log(action);
        let userName = document.getElementById("UserName").value
        url += `?userName=${userName}`
    }
    var xhttp = new XMLHttpRequest();
    xhttp.open("GET", url, true);
    xhttp.send();
    xhttp.onreadystatechange = function (event) {
        if (this.readyState == 4 && this.status == 200) {

            document.getElementById("errormessage").innerHTML = this.statusText;
        }
        else if (this.readyState == 4 && this.status == 404) {
            document.querySelector("#form-submit").submit();
        }
   };
}

The same ajax call is extended to include additional action methods. We can also check multiple fields on a form by retrieving them from the DOM and passing them via URL.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
functionvalidateForm(url, event){
event.preventDefault();
let splits = url.split('/');
let action = splits[splits.length - 1];
if(action.includes("CheckExistingUser")){
let userName = document.getElementById("UserName").value
let pswd = document.getElementById("Password").value
url += `?userName=${userName}&password=${pswd}`
}
elseif(action.includes("CheckExistingEmployee")){
let employeeId = document.getElementById("EmployeeId").value
let email = document.getElementById("Email").value
url += `?EmployeeId=${employeeId}&Email=${email}`
}
else{}
var xhttp = newXMLHttpRequest();
xhttp.open("GET", url, true);
xhttp.send();
xhttp.onreadystatechange = function(event){
if(this.readyState == 4&&this.status == 200)
{
document.getElementById("errormessage").innerHTML = this.statusText;
}
elseif(this.readyState == 4&&this.status == 404){
document.querySelector("#form-submit").submit();
}
};
}
function validateForm(url, event) { event.preventDefault(); let splits = url.split('/'); let action = splits[splits.length - 1]; if (action.includes("CheckExistingUser")) { let userName = document.getElementById("UserName").value let pswd = document.getElementById("Password").value url += `?userName=${userName}&password=${pswd}` } else if (action.includes("CheckExistingEmployee")) { let employeeId = document.getElementById("EmployeeId").value let email = document.getElementById("Email").value url += `?EmployeeId=${employeeId}&Email=${email}` } else {} var xhttp = new XMLHttpRequest(); xhttp.open("GET", url, true); xhttp.send(); xhttp.onreadystatechange = function (event) { if (this.readyState == 4 && this.status == 200) { document.getElementById("errormessage").innerHTML = this.statusText; } else if (this.readyState == 4 && this.status == 404) { document.querySelector("#form-submit").submit(); } }; }
function validateForm(url, event) {
    event.preventDefault();

    let splits = url.split('/');
    let action = splits[splits.length - 1];

    if (action.includes("CheckExistingUser")) {
        let userName = document.getElementById("UserName").value
        let pswd = document.getElementById("Password").value
        url += `?userName=${userName}&password=${pswd}`
    }
    else if (action.includes("CheckExistingEmployee")) {
        let employeeId = document.getElementById("EmployeeId").value
        let email = document.getElementById("Email").value
        url += `?EmployeeId=${employeeId}&Email=${email}`
    }
    else {}
    var xhttp = new XMLHttpRequest();
    xhttp.open("GET", url, true);
    xhttp.send();
    xhttp.onreadystatechange = function (event) {
        if (this.readyState == 4 && this.status == 200) 
        {
            document.getElementById("errormessage").innerHTML = this.statusText;
        }
        else if (this.readyState == 4 && this.status == 404) {
            document.querySelector("#form-submit").submit();
        }
    };
}

For the above scenario, the controller action method will look like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[AcceptVerbs("GET", "POST")]
public IActionResult CheckExistingEmployee(int EmployeeId, string Email)
{
if(!_employeeService.Employees.Any(u => u.EmployeeId == EmployeeId && u.Email == Email))
{
returnHttpNotFound();
}
returnnewHttpStatusCodeResult(200, $"Employee {Email} already exists.");
}
[AcceptVerbs("GET", "POST")] public IActionResult CheckExistingEmployee(int EmployeeId, string Email) { if (!_employeeService.Employees.Any(u => u.EmployeeId == EmployeeId && u.Email == Email)) { return HttpNotFound(); } return new HttpStatusCodeResult(200, $"Employee {Email} already exists."); }
[AcceptVerbs("GET", "POST")]
public IActionResult CheckExistingEmployee(int EmployeeId, string Email)
{
if (!_employeeService.Employees.Any(u => u.EmployeeId == EmployeeId && u.Email == Email))
{
return HttpNotFound();
}
return new HttpStatusCodeResult(200, $"Employee {Email} already exists.");
}

Hope you will find this blog helpful. (By writing 20 -25 lines of JavaScript, we have avoided the use of jQuery and jQuery validate libraries)

Leave a Reply

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

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

Akash Borkar

Akash Borkar is an IT professional who enjoys learning and knowledge-sharing. He works as Senior Technical Consultant at Perficient, Nagpur. He has experience in ASP.NET, Sitecore, JavaScript. He enjoys mentoring and team-building activities.

More from this Author

Follow Us