Remote Validation attribute in Asp.net MVC Razor

The article explains how to perform remote validation and mandatory settings required for remote validation.
As an example we are remotely validating username property of user with database. We are considering the username scenario in this article. We are going to validate whether the username entered by the user exist in database or not.

First Let us see What is Remote Validation ?
Demo


  • Remote validation allows the application to call the controller actions using client side script.
  • This is extremely useful when you want to perform a back end query without having to perform a full server postback.
  • Remote Validation is basically an ajax call to an action method which queries the database to validate username in our case and returns true or false based on validation result.
  • The process of Remote Validation does not involve postback.


ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace RemoteValidationMVCRazor.ViewModel
{
    public class UserViewModel
    {
        public string Name { get; set; }

        [Remote("IsValidUserName", "Home", ErrorMessage = "Username Exist !")]
        public string UserName { get; set; }

        [DataType(DataType.Password)]
        public string Password { get; set; }
    }
}
    

The above class is our simple ViewModel having three properties. We have applied Remote attribute on UserName property. We need to refer System.Web.Mvc namespace to use Remote attribute.
                                 The first parameter supplied is the Action method name i.e. IsValidUserName which will be called remotely. The second parameter supplied is the name of the controller Home in our case. The third parameter is the error message, this message will be shown if the validation fails.

This ViewModel we are going to use on our View as below:

View:
@model RemoteValidationMVCRazor.ViewModel.UserViewModel
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>


@using (Html.BeginForm())
{
    @Html.EditorForModel("UserViewModel")

    <br /><br />
    <input type="submit" value="Submit" />
}
    

In the above View, we have referred UserViewModel as model of the View. We have used EditorForModel helper to render controls for the property of the ViewModel. We have also created a submit button.

Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using RemoteValidationMVCRazor.Service;
using RemoteValidationMVCRazor.ViewModel;

namespace RemoteValidationMVCRazor.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            return View();
        }

        public JsonResult IsValidUserName(string UserName)
        {
            RemoteValidationService service = new RemoteValidationService();
            return Json(service.IsValidUserName(UserName), JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult Index(UserViewModel model)
        {
            RemoteValidationService service = new RemoteValidationService();
            service.SaveUser(model);
            return View();
        }

    }
}
    
We have a simple Controller named HomeController. We have three method inside the controller.
The first ActionResult method is used to render the Index view. The second JsonResult method is the method which will be called remotely to validate username. The third ActionResult method is the method where form is posted i.e. Index with HttpPost attribute. The parameter name UserName in the IsValidUserName method should match the property name in the ViewModel, otherwise the parameter value will be null.


Service Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using RemoteValidationMVCRazor.Models;
using RemoteValidationMVCRazor.ViewModel;

namespace RemoteValidationMVCRazor.Service
{
    public class RemoteValidationService
    {
        public bool IsValidUserName(string username)
        {
            using (RemoteValidationEntities dbContext = new RemoteValidationEntities())
            {
                return !dbContext.Users.Any(user => user.Username == username);
            }
        }

        public void SaveUser(UserViewModel model)
        {
            Users user = new Users();
            user.Name = model.Name;
            user.Username = model.UserName;
            user.Password = model.Password;
            using (RemoteValidationEntities dbContext = new RemoteValidationEntities())
            {
                dbContext.Users.AddObject(user);
                dbContext.SaveChanges();
            }
        }
    }
}
    
The service class has methods which interacts with the database. The first method is IsValidUserName which validates whether DB has user with same username. The Any Linq function returns a boolean value true if DB has username and Vice Versa, and we return negation of that boolean value. That means if user is present we return false as jSon result concluding validation failure, and if user is not present we return true concluding validation success.

Layout:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
</head>

<body>
    @RenderBody()
</body>
</html>
    
The layout must contains above three script files. These file are must, without these files remote validation is not possible. As we have referred this Layout on our View, we don't need to specify these scripts on View.

Web Config:




We need to have above keys set to true in web.config. If either of these keys are absent or set to false remote validation will not work.

How attribute works:
When the user enters some text in the control i.e. UserName in our case and clicks outside the onblur event is triggered on which IsValidUserName method is called, based on the validation if the user is not present in the database the validation message is shown on UI. Once the onblur event is triggered on making further changes in the same control, the IsValidUserName method is called as soon as you make change to the existing username entered i.e. (onkeyPress).
                            When the onblur event is triggered for the first time and ajax request is made to the IsValidUserName Method. The screenshot below shows the ajax call details. On subsequent changes to username the ajax request is made on keypress.



The ajax call details you can get under Network tab of develper tool.

Points to Remember:


  • Remote Validation is use to validate user input against database without full postback using ajax call.
  • The remotely method called should return boolean value as JsonResult.
  • The three script files must be referred on View or on Layout file i.e. jquery-1.5.1.min.js or higher version, jquery.validate.min.js, and jquery.validate.unobtrusive.min.js.
  • The web.config must contains keys ClientValidationEnabled and UnobtrusiveJavaScriptEnabled set to true under appSettings.
  • The Remote Validation will not work if the Javascript is disabled on the browser.

Also read article at below link which demonstrates how to cover up Remote validation when JavaScript is disabled on browser. 

0 comments:

Post a Comment