Asp.Net Web Api Data Annotations And Custom Validation Attributes Complete Guide

 Last Update:2025-06-23T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    8 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of ASP.NET Web API Data Annotations and Custom Validation Attributes

ASP.NET Web API Data Annotations and Custom Validation Attributes

What are Data Annotations?

Data Annotations are a set of attributes that you can apply to classes or properties in your ASP.NET Web API models. These attributes instruct the framework to perform certain actions, primarily validation, before data is processed. Data Annotations simplify the validation process while promoting a clean and separation of concerns approach.

Built-in Data Annotation Attributes

  1. [Required]

    • Ensures that the property has a value.
    • Usage: [Required(ErrorMessage = "Name is required")]
    • When applied to a property, it checks that the value is provided.
  2. [StringLength]

    • Validates the length of a string.
    • Usage: [StringLength(10, MinimumLength = 3, ErrorMessage = "Name must be between 3 and 10 characters")]
    • Allows specifying the maximum and minimum lengths of the string.
  3. [Range]

    • Ensures that a numeric or DateTime value falls within a specified range.
    • Usage: [Range(1, 12, ErrorMessage = "Value must be between 1 and 12")]
    • Ideal for numeric validation, ensuring values are within certain limits.
  4. [EmailAddress]

    • Validates that the property value conforms to an email address pattern.
    • Usage: [EmailAddress(ErrorMessage = "Invalid Email Address")]
    • Useful for validating email input fields.
  5. [Phone]

    • Validates that the property value conforms to a telephone number pattern.
    • Usage: [Phone(ErrorMessage = "Invalid Phone number")]
    • Useful for validating phone number input fields.
  6. [RegularExpression]

    • Applies a regular expression to validate the property.
    • Usage: [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$", ErrorMessage = "Invalid Name")]
    • Useful for complex pattern validations.
  7. [Compare]

    • Compares the value of the property with another property.
    • Usage: [Compare("Password", ErrorMessage = "Password mismatch")]
    • Typically used for password confirmation fields.
  8. [Url]

    • Validates that the property value is a well-formed URL.
    • Usage: [Url(ErrorMessage = "Invalid URL")]
    • Useful when validating URL input fields.
  9. [DataType]

    • Customizes the way an editor or display template is used.
    • Usage: [DataType(DataType.Password)]
    • Often used to customize how data is rendered in views.
  10. [Display]

    • Provides properties to control the display of the property.
    • Usage: [Display(Name = "User Name")]
    • Useful for UI labels and descriptions.

Implementing Custom Validation Attributes

While Data Annotations provide a powerful set of predefined validation attributes, there are scenarios where custom validation logic is necessary. Custom validation attributes are classes that inherit from System.ComponentModel.DataAnnotations.ValidationAttribute. Here’s how you can create and use custom validation attributes.

  1. Create a Custom Validation Attribute

    To illustrate, let’s create a custom validation attribute to ensure that a string property does not contain any numeric characters.

    using System;
    using System.ComponentModel.DataAnnotations;
    
    public class NoNumbersAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
                return ValidationResult.Success;
    
            string input = value.ToString();
    
            if (input.Any(char.IsDigit))
                return new ValidationResult("Input cannot contain numeric characters.");
    
            return ValidationResult.Success;
        }
    }
    
  2. Apply the Custom Validation Attribute to a Model

    Once created, you can apply the custom validation attribute to a model property like any other data annotation attribute.

    public class User
    {
        [Required(ErrorMessage = "Name is required")]
        [NoNumbers(ErrorMessage = "Name cannot contain numbers.")]
        public string Name { get; set; }
    }
    
  3. Handling Validation in Controllers

    In your ASP.NET Web API controllers, you can rely on the model validation mechanism to trigger the custom validation attribute.

Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement ASP.NET Web API Data Annotations and Custom Validation Attributes

Complete Examples, Step by Step for Beginners: ASP.NET Web API Data Annotations and Custom Validation Attributes

Prerequisites:

  • Visual Studio 2019 or later
  • ASP.NET Web API knowledge basics

Step 1: Create an ASP.NET Core Web API Project

  1. Open Visual Studio and select "Create a new project".
  2. In the "Create a new project" window, select "ASP.NET Core Web Application".
  3. Click "Next".
  4. Name your project WebApiValidationExample and choose a location for it.
  5. Click "Create".
  6. In the "Create a new ASP.NET Core Web Application" dialog, select the "ASP.NET Core Web API" template.
  7. Make sure "Authentication" is set to "None".
  8. Click "Create".

Step 2: Create a Model

Let's create a model called Employee for your API:

  1. Right-click on the Models folder in Solution Explorer and select "Add" > "Class".
  2. Name the file Employee.cs and click "Add".
  3. Define the Employee class with some properties and use Data Annotations for validation.
using System.ComponentModel.DataAnnotations;

namespace WebApiValidationExample.Models
{
    public class Employee
    {
        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "Name is required")]
        [StringLength(50, MinimumLength = 2, ErrorMessage = "Name should be between 2 and 50 characters.")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Email is required")]
        [EmailAddress(ErrorMessage = "Invalid Email Address")]
        [StringLength(100)]
        public string Email { get; set; }

        [Range(18, 60, ErrorMessage = "Age must be between 18 and 60")]
        public int Age { get; set; }

        [Required(ErrorMessage = "Department is required")]
        [StringLength(50)]
        public string Department { get; set; }
    }
}

Step 3: Create a Controller

  1. Right-click on the Controllers folder in Solution Explorer and select "Add" > "Controller".
  2. Choose "API Controller - Empty", name it EmployeesController, and click "Add".
  3. Define basic CRUD operations. Since we're focusing on validation, we'll focus on POST operation for simplicity.
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using WebApiValidationExample.Models;
using System.Linq;

namespace WebApiValidationExample.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeesController : ControllerBase
    {
        private static readonly List<Employee> Employees = new List<Employee>();

        // POST: api/Employees
        [HttpPost]
        public IActionResult PostEmployee([FromBody] Employee employee)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            Employees.Add(employee);
            
            return CreatedAtAction(nameof(GetEmployeeById), new { id = employee.Id }, employee);
        }

        // GET: api/Employees/{id}
        [HttpGet("{id}")]
        public IActionResult GetEmployeeById(int id)
        {
            var employee = Employees.FirstOrDefault(e => e.Id == id);
            if (employee == null)
            {
                return NotFound();
            }
            return Ok(employee);
        }
    }
}

Step 4: Create a Custom Validation Attribute

Let's create a custom validation attribute named ValidDepartment to check if the department name is one of the valid departments.

  1. Right-click on the Models folder in Solution Explorer and select "Add" > "Class".
  2. Name the file ValidDepartmentAttribute.cs and click "Add".
  3. Implement the ValidDepartmentAttribute class.
using System.ComponentModel.DataAnnotations;

namespace WebApiValidationExample.Models
{
    public class ValidDepartmentAttribute : ValidationAttribute
    {
        private readonly string[] _validDepartments = { "Sales", "Marketing", "IT", "HR" };

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
            {
                return new ValidationResult("Department is required");
            }

            string departmentName = value.ToString();

            if (!_validDepartments.Contains(departmentName))
            {
                return new ValidationResult($"Department should be one of: {string.Join(", ", _validDepartments)}");
            }

            return ValidationResult.Success;
        }
    }
}
  1. Update the Employee model to use this custom attribute.
using System.ComponentModel.DataAnnotations;

namespace WebApiValidationExample.Models
{
    public class Employee
    {
        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "Name is required")]
        [StringLength(50, MinimumLength = 2, ErrorMessage = "Name should be between 2 and 50 characters.")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Email is required")]
        [EmailAddress(ErrorMessage = "Invalid Email Address")]
        [StringLength(100)]
        public string Email { get; set; }

        [Range(18, 60, ErrorMessage = "Age must be between 18 and 60")]
        public int Age { get; set; }

        [Required(ErrorMessage = "Department is required")]
        [StringLength(50)]
        [ValidDepartment]
        public string Department { get; set; }
    }
}

Step 5: Testing the API

  1. Use Postman or Swagger UI to test the API.
  2. Incorrect Data:
    • Send an invalid Employee object with incorrect data types or values, e.g., Age as a negative number or non-string departments.
  3. Correct Data:
    • Send a valid Employee object ensuring all required fields are provided and values are within the specified ranges.

Example JSON for Post Operation:

Incorrect Example (missing Name and invalid Department):

{
    "email": "employee@example.com",
    "age": 25,
    "department": "RandomDept"
}

Response:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|187c0a85-4588a35af05988c0.",
    "errors": {
        "Name": [
            "Name is required"
        ],
        "Department": [
            "Department should be one of: Sales, Marketing, IT, HR"
        ]
    }
}

Correct Example:

{
    "name": "John Doe",
    "email": "john.doe@example.com",
    "age": 30,
    "department": "IT"
}

Response:

Top 10 Interview Questions & Answers on ASP.NET Web API Data Annotations and Custom Validation Attributes

Top 10 Questions and Answers on ASP.NET Web API Data Annotations and Custom Validation Attributes

1. What are ASP.NET Web API Data Annotations?

2. How do you use the [Required] attribute in ASP.NET Web API?

Answer: The [Required] attribute is used to ensure that a property is not null, empty, or a white space. For example:

public class Product
{
    [Required(ErrorMessage = "The product name is required")]
    public string Name { get; set; }
}

3. What is the purpose of the [StringLength] attribute?

Answer: The [StringLength] attribute specifies the minimum and maximum length of characters for a string property. It helps in validating the length of input data. For example:

public class Product
{
    [StringLength(100, MinimumLength = 2, ErrorMessage = "Product name must be between 2 and 100 characters")]
    public string Name { get; set; }
}

4. How can you use the [Range] attribute for numeric properties?

Answer: The [Range] attribute is used to specify the minimum and maximum allowable values for a numeric property. For example:

public class Product
{
    [Range(1, 100, ErrorMessage = "Price must be between 1 and 100")]
    public decimal Price { get; set; }
}

5. What is the [RegularExpression] attribute used for?

Answer: The [RegularExpression] attribute allows you to specify a regular expression pattern that the value of a property must match. It's useful for custom patterns and formats. For example:

public class Product
{
    [RegularExpression(@"^[A-Z]{2}\d{4}$", ErrorMessage = "Product code must follow the pattern 'AA1234'")]
    public string ProductCode { get; set; }
}

6. How do you create a Custom Validation Attribute in ASP.NET Web API?

Answer: To create a custom validation attribute, you need to inherit from the ValidationAttribute class and override the IsValid method. Here is an example of a custom attribute to check if a date is in the future:

public class FutureDateAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
            return ValidationResult.Success;

        DateTime date = (DateTime)value;

        if (date < DateTime.Now)
            return new ValidationResult("The date must be in the future");

        return ValidationResult.Success;
    }
}

public class Event
{
    [FutureDate(ErrorMessage = "Event date must be in the future")]
    public DateTime EventDate { get; set; }
}

7. Can you apply multiple data annotations to a single property?

Answer: Yes, multiple data annotations can be applied to a single property to enforce various validation rules. They are evaluated in the order they appear. For example:

public class Product
{
    [Required(ErrorMessage = "Price is required")]
    [Range(1, 100, ErrorMessage = "Price must be between 1 and 100")]
    public decimal Price { get; set; }
}

8. How do you handle validation errors in ASP.NET Web API?

Answer: ASP.NET Web API automatically applies the data annotation validation and if any validation fails, model state errors are added. You can check if the model is valid using ModelState.IsValid and handle the errors accordingly in your controller:

[HttpPost]
public IActionResult Create([FromBody] Product product)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);

    // Proceed to add product logic
    return Ok();
}

9. Can you apply data annotations to complex types or nested objects?

Answer: Yes, data annotations can be applied to complex types and nested objects. Validation will recursively check all the properties of these objects as long as they are public and nullable (or non-nullable and initialized). For example:

public class Order
{
    [Required]
    public Customer Customer { get; set; }
}

public class Customer
{
    [Required(ErrorMessage = "Customer name is required")]
    public string Name { get; set; }
}

10. How does client-side validation work with Data Annotations in ASP.NET Web API?

Answer: Client-side validation in ASP.NET Web API works through the integration of validation attributes with JavaScript libraries such as jQuery Unobtrusive Validation. When a form is submitted, client-side validation is triggered based on the data annotations applied to the model. Validation errors are displayed to the user without causing a round trip to the server. For this to work, the necessary HTML attributes must be enabled in the views, such as disabling unobtrusive validation by default in MVC configuration.

You May Like This Related .NET Topic

Login to post a comment.