Form validation
DataAnnotations attributes for the HeroKit validators. They work with ASP.NET Core model validation, Blazor's DataAnnotationsValidator, minimal API filters and Validator.TryValidateObject.
using System.ComponentModel.DataAnnotations;
using HeroKit.Validation;
public sealed class Customer
{
[Required, Tckn]
public string? IdentityNumber { get; set; }
[TaxId("TR")]
public string? TaxId { get; set; }
[Iban]
public string? Iban { get; set; }
[PhoneNumber("TR", MobileOnly = true, ErrorMessage = "Cep telefonu geçersiz.")]
public string? Mobile { get; set; }
[PostalCode("TR")]
public string? PostalCode { get; set; }
[VehiclePlate("TR")]
public string? Plate { get; set; }
[CardNumber]
public string? Card { get; set; }
[GibInvoiceNumber]
public string? InvoiceNumber { get; set; }
[Ettn]
public string? Ettn { get; set; }
}
| Attribute | Checks |
|---|---|
[Tckn] |
Turkish identity number checksum |
[Vkn] |
Turkish tax number checksum |
[Iban] |
ISO 13616 mod-97; national length where a country has IBAN rules (TR: 26) |
[CardNumber] |
Length and Luhn |
[GibInvoiceNumber] |
e-Fatura / e-Arşiv invoice number in the GİB format, for example ABC2026000000001 |
[Ettn] |
ETTN: a non-empty UUID in the 8-4-4-4-12 format |
[KepAddress] |
KEP address: an e-mail address on a .kep.tr domain |
[IdCardSerial] |
Chip identity card serial number, for example A12B34567 |
[Mersis] |
MERSİS number: "0", a valid VKN and a 5-digit serial |
[Gtin] |
Barcode number (EAN-8, UPC-A, EAN-13, GTIN-14) with the GS1 check digit |
[PhoneNumber("TR")] |
Phone number of a country; MobileOnly = true for mobiles |
[VehiclePlate("TR")] |
Vehicle plate of a country |
[PostalCode("TR")] |
Postal code of a country (TR: 5 digits, valid province prefix) |
[NationalId("TR")] |
National identity number of a country (TR: TCKN) |
[TaxId("TR")] |
Tax identifier of a country (TR: VKN or TCKN) |
The country attributes take an ISO 3166-1 alpha-2 code. The country is looked up in Countries when a value is validated, so a country you add with Countries.Register works too. See Countries and languages. A country without the needed rules throws NotSupportedException.
FluentValidation
The separate HeroKit.FluentValidation package adds the same checks as FluentValidation rules. The core package stays dependency-free.
dotnet add package HeroKit.FluentValidation
using FluentValidation;
using HeroKit.FluentValidation;
using HeroKit.Globalization;
public sealed class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(x => x.IdentityNumber).NotEmpty().Tckn();
RuleFor(x => x.Iban).Iban();
RuleFor(x => x.Mobile).PhoneNumber(Countries.Turkey, mobileOnly: true);
RuleFor(x => x.Plate).VehiclePlate(Countries.Turkey);
RuleFor(x => x.InvoiceNumber).GibInvoiceNumber();
}
}
Rules: Tckn, Vkn, Iban, CardNumber, GibInvoiceNumber, Ettn, Mersis, Gtin, KepAddress, IdCardSerial, and the country rules PhoneNumber(country, mobileOnly), VehiclePlate(country), PostalCode(country), NationalId(country), TaxId(country). Messages use {PropertyName}; replace them with WithMessage.
Notes
Null and empty values are valid, so optional fields stay optional. Add [Required] to require a value. Default messages are English and include the field name; set ErrorMessage or resource properties to localize them.