EmiratesKit.Annotations 1.0.1

dotnet add package EmiratesKit.Annotations --version 1.0.1
                    
NuGet\Install-Package EmiratesKit.Annotations -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EmiratesKit.Annotations" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EmiratesKit.Annotations" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="EmiratesKit.Annotations" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EmiratesKit.Annotations --version 1.0.1
                    
#r "nuget: EmiratesKit.Annotations, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EmiratesKit.Annotations@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EmiratesKit.Annotations&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=EmiratesKit.Annotations&version=1.0.1
                    
Install as a Cake Tool

EmiratesKit.Annotations

NuGet Build License: MIT

DataAnnotation validation attributes for UAE documents. Decorates model properties with [EmiratesId], [UaeIban], [UaeTrn], [UaeMobile], and [UaePassport] to trigger automatic validation during ASP.NET Core model binding.

Depends on EmiratesKit.Core, which is installed automatically.


Installation

dotnet add package EmiratesKit.Annotations

EmiratesKit.Core is installed automatically as a dependency. You do not need to install it separately.


When to Use This Package

Use EmiratesKit.Annotations when you want validation to run automatically as part of ASP.NET Core model binding — without writing any validation logic in your controllers or services.

When a request arrives, ASP.NET Core binds the request body to your model, runs all validation attributes, and populates ModelState. If any attribute fails, [ApiController] returns a 400 Bad Request response automatically before your action method is ever called.

If you need more control — conditional validation, cross-field rules, or custom error messages per rule — use EmiratesKit.FluentValidation instead.


Available Attributes

Attribute Validates Backed by
[EmiratesId] Emirates ID in format 784-YYYY-NNNNNNN-C Luhn algorithm
[UaeIban] UAE IBAN starting with AE, 23 characters Mod-97 algorithm
[UaeTrn] 15-digit TRN starting with 100 Structure check
[UaeMobile] UAE mobile in any accepted format Prefix lookup
[UaePassport] 1 uppercase letter + 7 digits Regex pattern

Basic Usage

Decorate your model properties with the relevant attribute:

using System.ComponentModel.DataAnnotations;
using EmiratesKit.Annotations.Attributes;

public class CreateCustomerRequest
{
    [Required]
    public string FullName { get; set; } = "";

    [Required]
    [EmiratesId]
    public string EmiratesId { get; set; } = "";

    [Required]
    [UaeMobile]
    public string Mobile { get; set; } = "";

    [UaeIban]
    public string? BankAccount { get; set; }

    [UaeTrn]
    public string? TaxRegistrationNumber { get; set; }

    [UaePassport]
    public string? PassportNumber { get; set; }
}

No changes are needed in the controller. With [ApiController], validation runs automatically:

[ApiController]
[Route("api/customers")]
public class CustomersController : ControllerBase
{
    [HttpPost]
    public IActionResult Create([FromBody] CreateCustomerRequest request)
    {
        // If EmiratesId or Mobile failed validation,
        // ASP.NET Core already returned 400 before reaching here.
        return Ok();
    }
}

Custom Error Messages

Every attribute accepts a custom ErrorMessage:

[EmiratesId(ErrorMessage = "Emirates ID must be in the format 784-YYYY-NNNNNNN-C.")]
public string EmiratesId { get; set; } = "";

[UaeMobile(ErrorMessage = "Please enter a valid UAE mobile number (e.g. 050 123 4567).")]
public string Mobile { get; set; } = "";

[UaeIban(ErrorMessage = "Bank account must be a valid UAE IBAN starting with AE.")]
public string? BankAccount { get; set; }

[UaeTrn(ErrorMessage = "Tax Registration Number must be 15 digits starting with 100.")]
public string? TaxRegistrationNumber { get; set; }

[UaePassport(ErrorMessage = "Passport number must be one letter followed by 7 digits.")]
public string? PassportNumber { get; set; }

Null and Empty Behaviour

All attributes in this package treat null and empty string as passing. They only validate when a value is present.

This is consistent with how standard .NET attributes like [EmailAddress] and [Phone] behave.

To make a field required, combine the attribute with [Required]:

// Optional — only validated when a value is provided
[UaeIban]
public string? BankAccount { get; set; }

// Required — must be present and must be a valid Emirates ID
[Required]
[EmiratesId]
public string EmiratesId { get; set; } = "";

Validation Response Format

When a request fails model validation, ASP.NET Core returns a 400 Bad Request with a ValidationProblemDetails body:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "errors": {
        "EmiratesId": [
            "Emirates ID must be in the format 784-YYYY-NNNNNNN-C."
        ],
        "Mobile": [
            "Please enter a valid UAE mobile number."
        ]
    }
}

The key in errors is the property name. The value is the list of error messages from the failing attributes.


Using with MVC and Razor Pages

The attributes work in all ASP.NET Core hosting models, not just Web API. For MVC controllers and Razor Pages, check ModelState.IsValid manually:

// MVC controller
[HttpPost]
public IActionResult Create(CreateCustomerRequest request)
{
    if (!ModelState.IsValid)
        return View(request);

    // proceed
    return RedirectToAction("Index");
}
// Razor Page
public IActionResult OnPost()
{
    if (!ModelState.IsValid)
        return Page();

    // proceed
    return RedirectToPage("Success");
}

Using with Manual Validation

If you are not using ASP.NET Core model binding, you can trigger attribute validation manually using Validator.TryValidateObject:

using System.ComponentModel.DataAnnotations;

var request = new CreateCustomerRequest
{
    EmiratesId = "784-1990-0000000-0",   // invalid checksum
    Mobile     = "+971501234567"
};

var context = new ValidationContext(request);
var results = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(request, context, results, validateAllProperties: true);

foreach (var result in results)
{
    Console.WriteLine(result.ErrorMessage);
    // Emirates ID checksum is invalid (Luhn algorithm failed).
}

Package Purpose
EmiratesKit.Core Core validators, static API, dependency injection support
EmiratesKit.FluentValidation FluentValidation rule extensions for complex validation scenarios

License

MIT License. Copyright 2026 Akhil P Vijayan.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 85 2/21/2026