A data annotation is a C# attribute placed on a class, property, or input parameter. In Entity Framework Core (EF Core), annotations add configuration metadata to entities. In ASP.NET Core, validation annotations set rules for incoming request data. section 4.3.3 section 6.1.2
For an EF Core entity such as BoardGame, annotations can describe individual mapping settings:
- [Table("BoardGames")] names the database table; [Key] identifies the key property. section 4.3.3
- [Required] marks a property as required, while [MaxLength(200)] limits a name’s length. section 4.3.3
EF Core also supports conventions and configuration through ModelBuilder’s Fluent API. Annotations override conventions, but Fluent API overrides annotations when rules conflict. Use annotations for entity-specific settings, conventions where they suffice, and Fluent API for model-wide settings. For example, the board-game join entities’ composite keys are configured with Fluent API. section 4.3.3
Limit an API page size
Place [Range(1, 100)] on the GET /BoardGames pageSize parameter. A request with pageSize=200 then returns HTTP 400 Bad Request instead of retrieving 200 games. The attribute supplies the boundary without a hand-written range check. section 6.1.2
Validation attributes can also apply to complex-type properties. ASP.NET Core model binding checks incoming values against these rules; its [ApiController] behavior can process validation results automatically, or the application can inspect ModelState for a customized response. section 6.4
Listing 4.2 BoardGame.cs file
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MyBGList.Models
{
[Table("BoardGames")] #1
public class BoardGame
{
[Key] #2
[Required]
public int Id { get; set; }
[Required]
[MaxLength(200)]
public string Name { get; set; } = null!;
[Required]
public int Year { get; set; }
[Required]
public int MinPlayers { get; set; }
[Required]
public int MaxPlayers { get; set; }
[Required]
public int PlayTime { get; set; }
[Required]
public int MinAge { get; set; }
[Required]
public int UsersRated { get; set; }
[Required]
[Precision(4, 2)]
public decimal RatingAverage { get; set; }
[Required]
public int BGGRank { get; set; }
[Required]
[Precision(4, 2)]
public decimal ComplexityAverage { get; set; }
[Required]
public int OwnedUsers { get; set; }
[Required]
public DateTime CreatedDate { get; set; }
[Required]
public DateTime LastModifiedDate { get; set; }
}
}
See the BoardGame entity for annotations placed directly on a class and its properties. section 4.3.3
public async Task<RestDTO<BoardGame[]>> Get(
int pageIndex = 0,
[Range(1, 100)]int pageSize = 10, #1
string? sortColumn = "Name",
string? sortOrder = "ASC",
string? filterQuery = null)
See [Range(1, 100)] applied directly to the pageSize endpoint parameter. section 6.1.2

