Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Model Validation in MVC4

0.00/5 (No votes)
10 Oct 2014 1  
In this article, we will see how to apply basic validations to a model in an ASP.NET MVC application.

Introduction

The most common web application security weakness is the failure to properly validate input from the client or environment. Data from the client should never be trusted for the client has every possibility to tamper with the data. So it needs to ensure that data is not only validated, but business rule is correct.

This article explains how to implement validation in an ASP.NET MVC application. I am using a simple form to demonstrate the basic validation in MVC4. Here, we will see different approaches to validate data from clientside and from serverside.

Basically, this article contains the following approaches:

  1. By using Data Annotations
  2. By using ModelState object (Explicit Model Validation)
  3. By using jQuery Validation plug-in
  4. By using Fluent Validation package

Using the Code

In MVC Model are the class which contains domain classes and the validations. Validation plays a core part in a Model.

First of all, let's create an application with sample model, view and controller. After that, we will apply different approaches to validate data.

Model (UserModel.cs)

namespace SampleApplication.Models
{
    public class UserModel
    {
        public string Name { get; set; }
        public string Email { get; set; }   
        public string MobileNo { get; set; }
    }
} 

View (User.cshtml)

@model SampleApplication.Models.UserModel
@{
    ViewBag.Title = "User Details";
}
<br /><br />
    @using (Html.BeginForm())
    {
       <fieldset>
        <legend>Form</legend>  
        <div class="form-group">
            @Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Name, new { @class = "form-control" })                
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
            </div>
        </div>        
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" class="btn btn-default" value="OK" />
            </div>
        </div>
      </fieldset>
   }

Controller (UserController.cs)

namespace SampleApplication.Controllers
{
    public class UserController : Controller
    {
        public ActionResult User()
        {
            return View();
        }
    }
}

 

By using Data Annotations

In ASP.NET MVC one of the best ways to validate a model is by using Data Annotations. It has a set of attributes and classes defined in the System.ComponentModel.DataAnnotations assembly. Data Annotations allow us to decorate model classes with metadata. This metadata describes a set of rules that are used to validate a property.

For using DataAnnotations, we need to add a reference to the System.ComponentModel.DataAnnotations assembly to model class.

using System.ComponentModel.DataAnnotations;

namespace SampleApplication.Models
{
    public class UserModel
    {
        [Required(ErrorMessage = "Please Enter Name")]
        [Display(Name = "Name")]
        public string Name { get; set; }
        
        [Required(ErrorMessage = "Please Enter Email Address")]
        [Display(Name = "Email")]
        [RegularExpression(@"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$", 
        ErrorMessage = "Please Enter Correct Email Address")]
        public string Email { get; set; } 

        [Required(ErrorMessage = "Please Enter Mobile No")]
        [Display(Name = "Mobile")]
        [StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)] 
        public string MobileNo { get; set; }
    }
} 

Now, we need to enable validationsummary and to add validation message to view page.

The @Html.ValidationSummary() method shows all the validation errors of a model in view page.

@Html.ValidationSummary(true)

@model SampleApplication.Models.UserModel
@{
    ViewBag.Title = "User Details";
}

<br /><br />

    @using (Html.BeginForm())
    {
       @Html.ValidationSummary(true)
       <fieldset>
        <legend>Form</legend>  
        <div class="form-group">
            @Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Name)                
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Email)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.MobileNo) 
            </div>
        </div>        
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" class="btn btn-default" value="OK" />
            </div>
        </div>
      </fieldset>
    }

UserController.cs

namespace SampleApplication.Controllers
{
    public class UserController : Controller
    {
        public ActionResult User()
        {
            return View();
        }

        [HttpPost]
        public ActionResult ServerMeta(RegistrationMetaModel mRegister)
        {
            if (ModelState.IsValid)
            {
                return View("Completed");
            }
            else
            {            
                 return View();
            }
        }
    }
}

 

By using ModelState object (Explicit Model Validation)

If you want to validate a model explicitly, then it is the best way to use ModelState Object within ActionMethod in controller. Just add an error message on ModelState with (key, value) pair manner and that message will be shown on the view whenever the data will not be validated in the model.

Model class will be shown as below:

namespace SampleApplication.Models
{
    public class UserModel
    {
        public string Name { get; set; }
        public string Email { get; set; }   
        public string MobileNo { get; set; }
    }
} 

Now we are going to add errormessage to ModelState object.

using System.Text.RegularExpressions;
using System.Web.Mvc;
using SampleApplication.Models;

namespace SampleApplication.Controllers
{
    public class UserController : Controller
    {
        public ActionResult User()
        {
            return View();
        }
       
        [HttpPost]
        public ActionResult User(UserModel model)
        {
            if (string.IsNullOrEmpty(model.Name))
            {
                ModelState.AddModelError("Name", "Please Enter Name");
            }
            if (!string.IsNullOrEmpty(model.Email))
            {
                string emailRegex = @"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$";
                Regex re = new Regex(emailRegex);
                if (!re.IsMatch(model.Email))
                {
                    ModelState.AddModelError("Email", "Please Enter Correct Email Address");
                }
            }
            else
            {
                ModelState.AddModelError("Email", "Please Enter Email Address");
            }
            if (string.IsNullOrEmpty(model.MobileNo))
            {
                ModelState.AddModelError("MobileNo", "Please enter your mobile no");
            }
            if (ModelState.IsValid)
            {
                return View("Completed");
            }
            else
            {            
                 return View();
            }
        }
    }
}

The view User.cshtml will display the validation message is as follows:

@model SampleApplication.Models.UserModel
@{
    ViewBag.Title = "User Details";
}
<br /><br />
    @using (Html.BeginForm())
    {
       @Html.ValidationSummary(true)
       <fieldset>
        <legend>Form</legend>  
        <div class="form-group">
            @Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Name)                
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Email)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.MobileNo) 
            </div>
        </div>        
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" class="btn btn-default" value="OK" />
            </div>
        </div>                                                                                                 </fieldset>
    }

 

By Using jQuery Validation Plug-in

The client side validation helps the application to reduce server loads and also it saves time of end user. So for client side validation, we are using following jQuery validation plug-in.

  1. jquery.validate.min.js
  2. jquery.validate.unobtrusive.min.js

Just add these files to your application if there are not present inside Scripts folder.

Scripts

First of all, we need to add the following config setting in web.config file.

<appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>

In MVC4, the above appsetting is by default enabled in config file. But we need to ensure that the ClientValidationEnabled and UnobtrusiveJavaScriptEnabled value are true before doing client side validation.

Now, we can write clientside JavaScript code to validate data or by using DataAnnotations attributes in Model.

Let's take advantage of DataAnnotations API in client side validation. So add DataAnnotations to model.

UserModel.cs

using System.ComponentModel.DataAnnotations;

namespace SampleApplication.Models
{
    public class UserModel
    {
        [Required(ErrorMessage = "Please Enter Name")]
        [Display(Name = "Name")]
        public string Name { get; set; }
        
        [Required(ErrorMessage = "Please Enter Email Address")]
        [Display(Name = "Email")]
        [RegularExpression(@"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$", 
        ErrorMessage = "Please Enter Correct Email Address")]
        public string Email { get; set; } 

        [Required(ErrorMessage = "Please Enter Mobile No")]
        [Display(Name = "Mobile")]
        [StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)] 
        public string MobileNo { get; set; }
    }
} 

UserController.cs

namespace SampleApplication.Controllers
{
    public class UserController : Controller
    {
        public ActionResult User()
        {
            return View();
        }

        [HttpPost]
        public ActionResult ServerMeta(RegistrationMetaModel mRegister)
        {
            if (ModelState.IsValid)
            {
                return View("Completed");
            }
            else
            {            
                 return View();
            }
        }
    }
}

During MVC project creation, the application adds a BundleConfig.cs file under App_Start folder. This class is used to include scripts and styles in bundle.

Include validation plug-in to BundleCollection object in BundleConfig.cs file.

The bundle code is:

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                             "~/Scripts/jquery.validate*"));

The page template (_Layout.cshtml) created for a new MVC 4 project contains this code at the end of the page which does not pull in the jQuery validation library.

@RenderSection("scripts", required: false)

In order to "turn on" jQuery validation for a single view, the following code needs to reside at the end of view.

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

User.cshtml

@model SampleApplication.Models.UserModel
@{
    ViewBag.Title = "User Details";
}
<br /><br />
    @using (Html.BeginForm())
    {
       @Html.ValidationSummary(true)
       <fieldset>
        <legend>Form</legend>  
        <div class="form-group">
            @Html.LabelFor(model => model.Name, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Name)                
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Email, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Email)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.MobileNo, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.MobileNo, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.MobileNo) 
            </div>
        </div>        
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" class="btn btn-default" value="OK" />
            </div>
        </div>                                                                                                 </fieldset>
    }
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

 

By Using Fluent Validation Package

FluentValidation library provides some easy way to unit test validation rules, one can split the validation rules completely from the underlying model. Specially, it will be helpful when you need to inject dependencies into your validation rules.

Now we are going to use FluentValidation class library by replacing DataAnnotations from Model.

Fluent Validation is available as a Nuget package, so search FluentValidation.MVC4 and install from Nuget Package Manager. After installing, you can find two new assemblies added to your application named as Fluent Validation and Fluent Validation.Mvc.

FluentValidation

Add a new class called UserModelValidator and place all the validation rules.

namespace SampleApplication.Models
{
    public class UserModelValidator : AbstractValidator<UserModel>
    {
        public UserModelValidator()
        {
            RuleFor(x => x.Name)
                .NotNull();
            RuleFor(x => x.Email)
                .NotNull()
                .EmailAddress();
            RuleFor(x => x.MobileNo)
                .NotNull()
                .Length(6, 10);
         }
     }
?}

Existing Model with DataAnnotations

using System.ComponentModel.DataAnnotations;

namespace SampleApplication.Models
{
    public class UserModel
    {
        [Required(ErrorMessage = "Please Enter Name")]
        [Display(Name = "Name")]
        public string Name { get; set; }
        
        [Required(ErrorMessage = "Please Enter Email Address")]
        [Display(Name = "Email")]
        [RegularExpression(@"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$", ErrorMessage = "Please Enter Correct Email Address")]
        public string Email { get; set; } 

        [Required(ErrorMessage = "Please Enter Mobile No")]
        [Display(Name = "Mobile")]
        [StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)] 
        public string MobileNo { get; set; }
    }
} 

Now link UserModelValidator validation class to the UserModel class by specifying it in the Validator attribute as follows:

[FluentValidation.Attributes.Validator(typeof(UserModelValidator))]
public class UserModel
{
    [Display(Name = "Name")]
    public string Name { get; set; }

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

    [Display(Name = "Mobile")]
    public string Mobileno { get; set; }
}

The last step is to call the FluentValidationModelValidatorProvider.Configure() method inside your global.asax file.

namespace SampleApplication
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            FluentValidationModelValidatorProvider.Configure();
        }
    }
}

For more information about FluentValidation, please refer to the following links:

The error messages are shown as below:

Validation Message

I have referred to the following links:

History

I will soon post the data-bind using AngularJS in MVC. Hope this helps beginners like me.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here