Updated on 30 Sep 2025 by Admin

Data Annotations in ASP.NET MVC

In ASP.NET WebForms, we had different validation controls like RequiredField validator, Compare validator, Range validator, RegularExpression validator, etc, to validate user inputs in server controls.

In ASP.NET MVC, we have DataAnnotations, which is much easier to use than WebForms' validators.

DataAnnotations are actually attributes in MVC, which can be applied to any model property. Each DataAnnotation has different validation rules.

Below are the different DataAnnotations available in ASP.NET MVC:

Attribute Description Syntax
Required Use it to make a field required. [Required(ErrorMessage="Please enter Name"),MaxLength(50)]
DataType Use it to specify the data type of the property of an entity explicitly. [DataType(DataType.EmailAddress)]
Range Use it to specify a numeric range of values for a field. [Range(20,60,ErrorMessage="Please enter between 20 and 60")]
StringLength Use it to specify the maximum and minimum length of a string property. [StringLength(50,ErrorMessage="Do not enter more than 50 characters")]
DisplayName Use it on a property so that it can be used in a view for display purposes. [Display(Name="Employee Name")]
MaxLength use it to specify the maximum accepted length for a property. [MaxLength(150)]
DisplayFormat Use this attribute to specify a specific date format. [DisplayFormat(DataFormatString = "{dd/MM/yyyy}")]
RegularExpression use it to explicitly define a regex pattern for any field [RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "Email is not valid.")]

Before using the DataAnnotations attribute to show a validation message on the view, it becomes important to know how validation actually works and what happens when submitted values do not satisfy the validation rules of the specified DataAnnotations attribute. I am pointing towards one important property called ModelState. Let's understand what ModelState actually is:

ModelState:

ModelState has two purposes:

  1. To store values submitted to the server.
  2. To store the validation error associated with those values.

The name ModelState is actually a little misleading; despite its name, it has nothing to do with a model class. Actually, it doesn't know anything about the model class; it only has names, values, and errors of submitted values.

ModelState is actually a property of the Controller class, so it can only be accessible to those classes that inherit from System.Web.MVC.Controller.

  • ModelState is of Type ModelStateDictionary that holds the collection of name and value pairs that were submitted to the server during a POST.
  • It contains a collection of error messages for each value submitted.

Now, it's time to implement validation. To display validation messages in the view, based on the validation rules of the specified DataAnnotations attribute or attached error message with the attribute, we can use the following HTML Helpers:

Html Helper Summary
@Html.ValidationMessage("Name")

Displays a validation message if an error exists for the specified field.

@Html.ValidationMessageFor(x=>x.Name)

Use it to display the validation error message specified in the model property using data-annotation.

@Html.ValidationSummary()

Use it to show all error messages at a time in an unordered list.

ValidationMessage

Like other HTML helpers, it is also an extension method of the HTML Helper class, which can be accessed in the view with @Html object, where HTML is an object of the Html helper class and the @ symbol is used to specify a server-side object in Razor view.

It is loosely typed and accepts a model property name as a string, which is used to show a validation message in the view. So, it is your duty to specify the same name to this HTML Helper as your property name.

public static MvcHtmlString ValidationMessage(this HtmlHelper htmlHelper, string modelName, IDictionary<string, object> htmlAttributes);

As I have already mentioned, ModelState captures all the values and errors associated with the values that are submitted to the server. The ASP.NET MVC framework automatically enforces these validation errors on HTML helpers if ModelState contains any related errors.

ValidationMessageFor

It also has the same purpose, i.e., to show the validation messages in the MVC View. It is the strongly-typed version of ValidationMessage HTML Helper, which can be accessed with @Html syntax in the Razor view.

public static MvcHtmlString ValidationMessageFor<tmodel, tproperty>(this HtmlHelper<tmodel>htmlHelper, Expression<func<tmodel, tproperty>> expression, string validationMessage)

ValidationSummary

If you want to show all the validation errors in one go, this extension method is the best for you. Validation summary generates an unordered list of validation messages that are in the ModelStateDictionary object.

public static MvcHtmlString ValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors, string message);

Now, let's take examples to show both built-in error messages and custom errors.

  • Step 1. Create a model class with some properties and DataAnnotations attributes as follows:
    public class Employee
    {
    [Required]
    public string Name { get; set; }
    [Required]
    [Range(18,45)]
    public int Age { get; set; }
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }
    [DataType(DataType.PhoneNumber)]
    public int Phone { get; set; }
    }
    
    
  • Step 2. Create two Action Methods, one for returning a view and the other to capture validation errors or to save the value in the database.
    public ActionResult SaveEmployee(Employee emp)
    {
    if (ModelState.IsValid)
    {
    //write logic to save into the database here
    }
    return View("Validation",emp);
    }
    public ActionResult Validation()
    {
    return View();
    }
    
    
  • Step 3. Design the view using HTML helpers like below:
    @{
    ViewBag.Title = "Validation";
    }
    <h2>Validation</h2>
    @using MVCExample.Models
    @model Employee
    <style>
    .error{
    color:red;
    }
    </style>
    <form action="/Student/SaveEmployee" method="post">
    <table>
    <tr>
    <td>@Html.LabelFor(l=>l.Name)</td>
    <td>@Html.TextBoxFor(m=>m.Name) @Html.ValidationMessageFor(m => m.Name, "", new {@class="error" })</td>
    </tr>
    <tr>
    <td>@Html.LabelFor(l => l.Age)</td>
    <td>@Html.TextBoxFor(m => m.Age)@Html.ValidationMessageFor(m => m.Age, "", new { @class = "error" })</td>
    </tr>
    <tr>
    <td>@Html.LabelFor(l => l.Email)</td>
    <td>@Html.TextBoxFor(m => m.Email)@Html.ValidationMessageFor(m => m.Email, "", new { @class = "error" })</td>
    </tr>
    <tr>
    <td>@Html.LabelFor(l => l.Phone)</td>
    <td>@Html.TextBoxFor(m => m.Phone)@Html.ValidationMessageFor(m => m.Phone, "", new { @class = "error" })</td>
    </tr>
    <tr>
    <td colspan="2"><button type="submit">Save</button></td>
    </tr>
    </table>
    </form>
    
    
  • Now, run the application and violate some validation intentionally and check whether validations are working or not.

    Validation in MVC
    validation in MVC

As you can see, the inbuilt validation error messages are self-sufficient, yet if you want custom error messages, you have two options:-

  1. Use the overloaded version of the DataAnnotations attribute to specify custom errors like below:
    [Required(ErrorMessage="can not be empty")]
    public string Name { get; set; }
    [Required]
    [Range(18,45,ErrorMessage="Age must be between 18 and 45")]
    public int Age { get; set; }
    
    
  2. Use the overloaded version of the HTML Helper method to specify a custom error.
    @Html.ValidationMessageFor(m => m.Name,"can not be empty", new {@class="error" })
    
    

Custom validation Attribute:

All the available DataAnnotations attributes are good and sufficient for most of the business validations. However, there may be situations where these attributes fail to serve the purpose, and you need to write your own validation logic.

ASP.NET MVC provides us a way to make our own custom validation attribute as per our requirement. To create a custom validation attribute, we must inherit our class from ValidationAttribute and implement (override) its IsValid method.

Let's understand it with an example.

Suppose we have to validate whether the User Name is already in use or available. We will create a custom validation attribute for this as follows:

public class UserNameCheck:ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string[] names = {"sachin","arjun","vikash","Govinda","Salman" };
Employee emp = (Employee)validationContext.ObjectInstance;
bool istrue = names.Any(x => x == emp.Name);
if (istrue)
{
return new ValidationResult("UserName is in use");
}
return ValidationResult.Success;
}
}

1. I have used the same Employee model so that it would be easy for you to understand.
2. I have used the second overloaded version of IsValid(), which accepts two parameters: one is the incoming submitted value, and the other is ValidationContext. ValidationContext provides access to the containing container, which in turn gives us access to the class that is using it.
3. ValidationContext.ObjectInstance is used to create an object of the container class. In our case, we are about to use this attribute with the Employee model class, so I have cast it as an Employee Type.
4. I have not used any Database logic; you are free to write any logic you want.
5. If an error occurs, return an instance of ValidationResult with an error message as a parameter or return Success, which is a read-only static field.
6. Mark the Name property of the Employee class with this custom attribute like below.

public class Employee
{
[Required(ErrorMessage="can not be empty")]
[UserNameCheck]
public string Name { get; set; }
[Required]
[Range(18,45,ErrorMessage="Age must be between 18 and 45")]
public int Age { get; set; }
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.PhoneNumber)]
public int Phone { get; set; }
}

We have already created the view in the previous example; now it's time to run the application and check the validation.

custom validation
custom validation user name is in use

You need to login to post a comment.

Sharpen Your Skills with These Next Guides