Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Creating Your Own Validation Attribute In MVC and Web API 2.0

DZone's Guide to

Creating Your Own Validation Attribute In MVC and Web API 2.0

In this post, we go through a tutorial on how to create data validation in a web application using both MVC and Web API 2.0.

· Web Dev Zone ·
Free Resource

Jumpstart your Angular applications with Indigo.Design, a unified platform for visual design, UX prototyping, code generation, and app development.

Data validation in an application is one of the major tasks for the developer now-a-days. Data validation is the process of ensuring that the data entered by any users is correct and is useful. It uses routines, often called validation rules, validation constraints or check routines, which check for the correctness, meaningfulness, and security of data, that gets put into a web application. These rules are mainly implemented in UI, business logic, and databases.

If we check in any web application, we will mainly find validations in the UI. As the user interface is the primary source, where the user can enter invalid data in the application, we mainly focus on UI validation.

In MVC, we have data notation attributes, which will ensure data integrity while it's being entered in.

All data annotation attributes are included in the System.ComponentModel.DataAnnotations namespace. Various data annotation attributes give you a simple way to perform validations on model data. These attributes are helpful for the common validation patterns like Required, Range, StringLength, etc.

It can perform the validation on both the client- and server-side of an application.

The main Data Validation attributes are given below.

  1. Required - It ensures that the value must be provided to the model property.
  2. Range - The data should be in a specific range, for example, age should not be between 1 to 18.
  3. StringLength - You can specify the minimum and maximum length of a property's value.
  4. Compare - It is used to compare one property value with another.
  5. Regular Expression - The value should match regular expressions, e.g. E-mail, phone, URL, etc.

However, sometimes when a validator fails to validate certain business rules, we require custom validation for custom business rules. So, we will see how we can implement these in an MVC application.

Requirements

Here, I have a model, as shown below.

public class RegisterViewModel  
   {  
       [Required]  
       [EmailAddress]  
       [Display(Name = "Email")]  
       public string Email { get; set; }  

       [Required]  
       [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]  
       [DataType(DataType.Password)]  
       [Display(Name = "Password")]  
       public string Password { get; set; }  
       [Required(ErrorMessage ="First Name is Required")]  
       public string FirstName { get; set; }  
       [Required(ErrorMessage = "Last Name is Required")]  
       public string LastName { get; set; }  


public string Country { get; set; }


   }  

Thus, I have a country property. Here, I want to implement the validation. The application should accept only these 3 countries: India, Pakistan, Nepal.

As of now, I don't find any validation attributes which will fulfill my requirement, so I will go for Custom Validation.

Before implementing Custom Validation, we should know about a class, i.e. ValidationAttribute.

The ValidationAttribute class is an abstract class, which contains the IsValid virtual method. The  IsValid method takes the value and ValidationContext object as the input parameters.

Value represents the value of the model property for which this Custom Validation applies. ValidationContext describes the context in which validation check is performed.

Thus, for this custom validation, add a new class called checkCountry as shown below and derive it from the ValidationAttribute class.

public class CustomValidation  
    {  
        public sealed class checkCountry : ValidationAttribute  
        {  
            public String AllowCountry { get; set; }  

            protected override ValidationResult IsValid(object country, ValidationContext validationContext)  
            {  
                string[] myarr = AllowCountry.ToString().Split(',');  
                if(myarr.Contains(country))  
                {  
                    return ValidationResult.Success;  
                }  
                else  
                {  
                    return new ValidationResult("Please choose a valid country eg.(India,Pakistan,Nepal");  
                }  
            }  

        }  

    }   

Now, use the namespace given below and modify the model, as shown below.

using System.ComponentModel.DataAnnotations;  
using static customValidation.CustomValidation; 

Now, you have the attribute checkCountry in the model property, as shown.

[checkCountry(AllowCountry ="India,Pakistan,Nepal",ErrorMessage = ("Please choose a valid country eg.(India,Pakistan,Nepal")]  
       public string Country { get; set; }  

Now, add the details given below and click Register in View.

Image title

The source code for the View is given below.

@model customValidation.Models.RegisterViewModel  
@{  
//ViewBag.Title = "Register";  
}  

<h2>@ViewBag.Title.</h2>  



@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))  
{  
    @Html.AntiForgeryToken()  
    <h4>Create a new account.</h4>  
    <hr />  
    @*@Html.ValidationSummary("", new { @class = "text-danger" })*@  
    <div >  
        <div class="form-group" >  
            @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })  
            <div class="col-md-10">  
                @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })  
               @Html.ValidationMessageFor(model => model.Email,null, new { @class = "text-danger" })   
            </div>  
        </div>  
        <div class="form-group">  
            @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })  
            <div class="col-md-10">  
                @Html.PasswordFor(m => m.Password, new { @class = "form-control" })  
                @Html.ValidationMessageFor(model => model.Password, null, new { @class = "text-danger" })  
            </div>  
        </div>  
        <div class="form-group">  
            @Html.LabelFor(m => m.FirstName, new { @class = "col-md-2 control-label" })  
            <div class="col-md-10">  
                @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })  
                @Html.ValidationMessageFor(model => model.FirstName, null, new { @class = "text-danger" })  
            </div>  
        </div>  
        <div class="form-group">  
            @Html.LabelFor(m => m.LastName, new { @class = "col-md-2 control-label" })  
            <div class="col-md-10">  
                @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })  
                @Html.ValidationMessageFor(model => model.LastName, null, new { @class = "text-danger" })  
            </div>  
        </div>  
        <div class="form-group">  
            @Html.LabelFor(m => m.Country, new { @class = "col-md-2 control-label" })  
            <div class="col-md-10">  
                @Html.TextBoxFor(m => m.Country, new { @class = "form-control" })  
                @Html.ValidationMessageFor(model => model.Country, null, new { @class = "text-danger" })  
            </div>  
        </div>  
        <div class="form-group">  
            <div class="col-md-offset-2 col-md-10">  
                <input type="submit" class="btn btn-default" value="Register" />  
            </div>  
        </div>  
    </div>  
}  

@section Scripts {  
    @Scripts.Render("~/bundles/jqueryval")  
}   

Now, just put a breakpoint in and check the execution. 

Image title

Not, it will check if the entered county is present in allowCountry by splitting the string, if not, then it will return an error message.

Image title

The Controller code is given below:

// POST: /Account/Register  
       [HttpPost]  
       [AllowAnonymous]  
       [ValidateAntiForgeryToken]  
       public async Task<ActionResult> Register(RegisterViewModel model)  
       {  
           if (ModelState.IsValid)  
           {  
               var user = new ApplicationUser { UserName = model.Email, Email = model.Email };  
               var result = await UserManager.CreateAsync(user, model.Password);  
               if (result.Succeeded)  
               {  
                   await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);  



                   return RedirectToAction("Index", "Home");  
               }  
               AddErrors(result);  
           }  

           // If we got this far, something failed, redisplay form  
           return View(model);  
       }  

Here, the output is produced.

Image title

In this way, we can create our own validation attributes and can use them in the project.

Now, check this functionality in Web API 2.0.

Create a MVC WebAPI project.

Add the model given below.

  {  
      [Required]  
      [EmailAddress]  
      [Display(Name = "Email")]  
      public string Email { get; set; }  
      public string FirstName { get; set; }  
      [Required(ErrorMessage = "Last Name is Required")]  
      public string LastName { get; set; }  

      public string Country { get; set; }  



  }  

Now, add a class to create your own validation, as shown below.

public sealed class checkCountry : ValidationAttribute  
   {  
       public String AllowCountry { get; set; }  

       protected override ValidationResult IsValid(object country, ValidationContext validationContext)  
       {  
           string[] myarr = AllowCountry.ToString().Split(',');  
           if (myarr.Contains(country))  
           {  
               return ValidationResult.Success;  
           }  
           else  
           {  
               return new ValidationResult("Please choose a valid country eg.(India,Pakistan,Nepal)");  
           }  
       }  

   }  

Image title

public class Register  
   {  
       [Required]  
       [EmailAddress]  
       [Display(Name = "Email")]  
       public string Email { get; set; }  
       public string FirstName { get; set; }  
       [Required(ErrorMessage = "Last Name is Required")]  
       public string LastName { get; set; }  

       [checkCountry(AllowCountry = "India,Pakistan,Nepal", ErrorMessage = "please enter a valid country eg( India,SriLanka,Nepal.)")]  
       public string Country { get; set; }  



   }  

Now, the Register Controller is shown.

[Route("Register")]  
       public async Task<HttpResponseMessage> RegisterUser(Register obj)  
       {  
           Dictionary<string, object> dict = new Dictionary<string, object>();  

           if (!ModelState.IsValid)  
           {  
               string errordetails = "";  
               var errors = new List<string>();  
               foreach (var state in ModelState)  
               {  
                   foreach (var error in state.Value.Errors)  
                   {  
                       string p = error.ErrorMessage;  
                       errordetails = errordetails + error.ErrorMessage;  

                   }  
               }  

               dict.Add("error", errordetails);  
               return Request.CreateResponse(HttpStatusCode.BadRequest, dict);  

           }  
           else  
           {  
               dict.Add("Success", "Register successfully");  
               HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK,dict);  
               return response;  
           }  

       }  

Now, check the Register method, using Postman.

Let's put an invalid country and test it first.

Image title

Now, put the valid data and test the result.

Image title


Thus, in this way, we can create our validation attribute and use it in both MVC and WebAPI.

Take a look at the Indigo.Design sample applications to learn more about how apps are created with design to code software.

Topics:
c# ,webapi ,mvc ,validation and verification ,web dev

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}