Data validation in ASP.NET Core is a crucial aspect of ensuring that the data received from users meets specific criteria before it is processed or stored. ASP.NET Core provides a robust validation framework that allows developers to define validation rules using data annotations, custom validation attributes, and model state validation. This guide will explain how to implement data validation in an ASP.NET Core application.
Key Features of Data Validation
- Data Annotations: ASP.NET Core supports a variety of built-in data annotations that can be applied to model properties to enforce validation rules.
- Model State Validation: The framework automatically validates the model state during model binding, allowing you to check for validation errors easily.
- Custom Validation: You can create custom validation attributes to implement complex validation logic that is not covered by built-in annotations.
Step 1: Define a Model with Data Annotations
To demonstrate data validation, let's create a simple model class that represents a product. We will use data annotations to specify validation rules.
using System.ComponentModel.DataAnnotations;
public class Product
{
public int Id { get; set; }
[Required(ErrorMessage = "Product name is required.")]
[StringLength(100, ErrorMessage = "Product name cannot exceed 100 characters.")]
public string Name { get; set; }
[Range(0.01, 10000.00, ErrorMessage = "Price must be between 0.01 and 10,000.00.")]
public decimal Price { get; set; }
}
Explanation of the Model Code
In the Product
class:
- Properties: The class defines three properties:
Id
,Name
, andPrice
. - Data Annotations:
- The
[Required]
attribute indicates that theName
property must have a value. If it is not provided, a validation error will occur. - The
[StringLength(100)]
attribute limits the length of the name to 100 characters, with a custom error message if the validation fails. - The
[Range(0.01, 10000.00)]
attribute specifies that thePrice
must be between 0.01 and 10,000.00, also with a custom error message.
- The
Step 2: Using the Model in a Controller
Once the model is defined, you can use it in a controller to handle HTTP requests and validate the incoming data. Below is an example of a controller that uses the Product
model.
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private static List<Product> products = new List<Product>();
// Action method to create a new product
[HttpPost]
public IActionResult CreateProduct([FromBody] Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState); // Returns a 400 Bad Request if the model is invalid
}
product.Id = products.Count + 1; // Assign a new ID
products.Add(product); // Add the new product to the list
return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, product); // Returns a 201 Created response
}
// Action method to get a product by ID
[HttpGet("{id}")]
public IActionResult GetProductById(int id)
{
var product = products.Find(p => p.Id == id);
if (product == null)
{
return NotFound(); // Returns a 404 Not Found response
}
return Ok(product); // Returns the product as a JSON response
}
}
Explanation of the Controller Code
In the Products Controller
class:
- CreateProduct Action: This action method accepts a
Product
object from the request body. The[FromBody]
attribute indicates that the model binder should look for the data in the request body. If the model state is invalid (e.g., required fields are missing or values are out of range), it returns a 400 Bad Request response with validation errors. - GetProductById Action: This method retrieves a product by its ID. If the product is not found, it returns a 404 Not Found response; otherwise, it returns the product as a JSON response.
Step 3: Custom Validation Attributes
In addition to built-in data annotations, you can create custom validation attributes for more complex validation scenarios. Below is an example of a custom validation attribute that checks if the price is a positive value.
using System;
using System.ComponentModel.DataAnnotations;
public class PositivePriceAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value is decimal price && price <= 0)
{
return new ValidationResult("Price must be a positive value.");
}
return ValidationResult.Success;
}
}
Using Custom Validation in the Model
You can apply the custom validation attribute to the Price
property in the Product
model as follows:
public class Product
{
public int Id { get; set; }
[Required(ErrorMessage = "Product name is required.")]
[StringLength(100, ErrorMessage = "Product name cannot exceed 100 characters.")]
public string Name { get; set; }
[PositivePrice] // Custom validation attribute
[Range(0.01, 10000.00, ErrorMessage = "Price must be between 0.01 and 10,000.00.")]
public decimal Price { get; set; }
}
Conclusion
Implementing data validation in ASP.NET Core is essential for maintaining data integrity and providing a better user experience. By using data annotations, model state validation, and custom validation attributes, developers can ensure that the data received from users is valid before processing it. This approach not only enhances the security of the application but also simplifies error handling and improves the overall quality of the code.