Search in Help for developer site.

Wednesday 31 August 2016

Implement client and server validation using custom validation attributes in Asp.net MVC

Hi Folks
Today we are going to learn how to implement Client side validation and Server side validation using Custom Data annotation attributes in Asp.Net MVC.
Well,
First i would like to list out some pre-defined Data Annotations which are being used in Asp.Net MVC.
  •  [Required]
  • [Compare]
  • [DataType]
  • [DisplayFormat] and many more

Some times developers want to validate the data which is no more possible with predefined data annotations as per the requirement. For Ex : In Job application form, developer wants to validate person age to restrict the candidate from filling the form and enable them to apply only for particular age .So here we don't get any data annotation attribute to check age constraint.So here we are going to implement custom data annotations to validate data as per our requirement.




Step 1:

Create a New Asp.Net MVC Web Application and select Basic Template.





Step 2:
Create a model class.
Go to Models folder and right click ,  Add -->Class.Give name as 'UserProfile'.
Now,I will add some properties for the class.


 


In above picture you can observe i have added some custom attributes( [CheckAge] and [ExcludeChar]) along with predefined attributes to validate the data.

Step 3:

  • Well,now i will create one folder from root directory of the application as 'CustomAttributes'
  • Inside this folder  i will create one class and  ll be writing code to  create and implement custom validation attributes.
  • Have a  look at code which implements custom validation attributes..



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

namespace CustomValidation.CustomAttributes
{
    public class ExcludeChar : ValidationAttribute, IClientValidatable
    {
        private string _chars;
        private string errorMessage;

        public ExcludeChar(string chars)
            : base("{0} contains invalid character.")
        {
            _chars = chars;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {

                for (int i = 0; i < _chars.Length; i++)
                {

                    var valueAsString = value.ToString();
                    if (valueAsString.Contains(_chars[i]))
                    {
                        errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);

                    }
                }
            }

            return ValidationResult.Success;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules
     (ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule mcvrTwo = new ModelClientValidationRule();
            mcvrTwo.ValidationType = "excludechar";
            mcvrTwo.ErrorMessage = "User Name contains invalid character";
            mcvrTwo.ValidationParameters.Add("otherpropertyname", _chars);

            yield return mcvrTwo;
        }
    }

    public class CheckAge : ValidationAttribute
    {
        private int _UserAge;


        public CheckAge(int Age, string errormsg)
            : base(errormsg)
        {
            this._UserAge = Age;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            ValidationResult validationResult = ValidationResult.Success;

            if (value != null)
            {
                var UserAgeVal = Convert.ToInt32(value);
                if (UserAgeVal > _UserAge)
                    validationResult = new ValidationResult(ErrorMessageString);
            }
            return validationResult;

        }
    }
}

Now, we just go through the code and analyze it. We have created ExcludeChar class and this class inherihating parent class called ‘ValidationAttribute’ class  and ‘IClientValidatable’ interface.
·         ExcludeChar class using parent’s method  IsValid() and overrides it to do some logic to exclude unwanted character from being entered.
·         It also implements  GetClientValidationRules() method of IClientValidatable interface to enable unobtrusive client validation.

 Note :

For Server side validation only IsValid() method is enough to fire the validation.But only the thing is we need to check modelstate.IsValid() in post request method of controller as shown.

[HttpPost]
        public ActionResult UserProfile(UserProfile model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            return View(model);
        }




Step 4: Create Controller

 




Step 5: Create Views

·        Index View
·        UserProfile View

  •   Index View



@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<br />
<br />
<h2>Index</h2>
<hr />
<br />
<textarea class="form-control" rows="3" readonly="readonly" style="height: 50%; width: 50%">
    Hi Guys..This Appplication Demonstrates How to impliment Client Validation and Server Validation using Custom Data Annotation Attributes.
</textarea>



  •    UserProfile View


@model CustomValidation.Models.UserProfile

@{
    ViewBag.Title = "UserProfile";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<br /><br />
<h2>UserProfile</h2>


<hr />
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="~/Scripts/jquery-migrate-1.2.1.js"></script>
<script src="~/Scripts/CustomVal.js"></script>
<script src="~/Scripts/jquery-ui-1.11.2.min.js"></script>

<script>
    $(function () { 
        $("#DOB").datepicker(); 
    });

</script>


@using (Html.BeginForm("UserProfile", "Home", FormMethod.Post))
{
    <div>
        <div>
            <p>
                @Html.LabelFor(m => m.UserName)
            </p>
            <div>
                @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.UserName)
            </div>

            <p>
                @Html.LabelFor(m => m.Age)
            </p>
            <div>
                @Html.TextBoxFor(m => m.Age, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Age)
            </div>

            <p>
                @Html.LabelFor(m => m.DOB)
            </p>
            <div>
                @Html.TextBoxFor(m => m.DOB, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.DOB)
            </div>

            <p>
                @Html.LabelFor(m => m.City)
            </p>
            <div>
                @Html.TextBoxFor(m => m.City, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.City)
            </div>

            <p>
                @Html.LabelFor(m => m.Address)
            </p>
            <div>
                @Html.TextBoxFor(m => m.Address, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Address)
            </div>
            <div style="padding-top: 15px">
                <input type="submit" value="Save" class="btn btn-success" />
            </div>
        </div>
    </di>



Step 5: Create javascript file and add jquery code to handle unobtrusive client validation



And code is as follows


$.validator.addMethod("excludechar", function (value, element, param) {
    var characterReg = new RegExp("^[a-zA-Z]+$");
    var result = false;

    if (characterReg.test(value)) {
        result = true;
    }
    return result;
});

$.validator.unobtrusive.adapters.add
      ("excludechar", ["otherpropertyname"], function (options) {
          options.rules["excludechar"] = options.params.otherpropertyname;
          options.messages["excludechar"] = options.message;
      });


Important Note:

You can observe in GetClientValidationRules() of CustomAttribute Class,there we have written following line of code.

mcvrTwo.ValidationType = "excludechar";
mcvrTwo.ErrorMessage = "User Name contains invalid character";
mcvrTwo.ValidationParameters.Add("otherpropertyname", _chars);

Here we have given validation type as ‘excludechar and parametername as ‘otherpropertyname’.We just re-called this piece of code only because that the methods jquery.validator.add() and $.validator.unobtrusive.adapters.add() have got some parameters.So name of this parameter should match validationtype and validationpaarameters of property of class ‘ModelClientValidationRule’.

Step 6 :

Add Layout File.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>

    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jqueryui")
    @Styles.Render("~/Content/themes/base/css")    
</head>

<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", null, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "UserProfile", "Home")</li>
                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>
</body>
</html>

Note : 

Add required jquery plugins and here we have used Bootstrap to improve look and feel of the application.
  • Jquery plugins used are :

·        jquery-1.9.1
·        jquery.validate
·        jquery.validate.unobtrusive


Step 7 : Run the Application and see the output.

1.Home Page

 



2.User Profile

 






  •         As you can see in above pic, when user clicks Save button it will through server validation.


 


  • Client side validation thrown when user enters invalid characters n gets out of focus .Here we used custom validation attribute to avoid invalid characters from being inserted.


 


  • Server side validation thrown when user enters user age more than 50 n clicks save button.Here we used custom validation attribute to restrict  the user   from being saved who has age more than 50.
Thank you guys.. I hope this post will be helpful for you.And let me know if you have any concerns and any issues.




7 comments: