Create or modify a CoreEx validator in the Application layer. USE FOR: new Validator<T,TSelf> (no injection), new Validator<T> with constructor injection, AbstractValidator<T,TSelf> (FluentValidation-style), adding rules to an existing validator, nested entity/collection/dictionary validators. DO NOT USE FOR: domain invariants in aggregates, FluentValidation NuGet package, Infrastructure-layer checks.
Scanned 8/31/2026
Install to Claude Code
npx -y skills add Avanade/CoreEx --skill coreex-validator --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Coreex Validator?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/avanade-coreex-validator)More formats (shields.io, HTML) on the badges page.
---
name: coreex-validator
description: "Create or modify a CoreEx validator in the Application layer. USE FOR: new Validator<T,TSelf> (no injection), new Validator<T> with constructor injection, AbstractValidator<T,TSelf> (FluentValidation-style), adding rules to an existing validator, nested entity/collection/dictionary validators. DO NOT USE FOR: domain invariants in aggregates, FluentValidation NuGet package, Infrastructure-layer checks."
argument-hint: "Optional: contract type, validator name, list of properties to validate, any async/database checks needed"
tags: ["validators", "validation", "application-layer", "coreex", "fluent-rules", "async"]
---
<!--
AI workflow asset — dual-audience notice:
- In the Avanade/CoreEx repository: this file is the authored source. Edit it here.
- In a consumer repository: this file was generated by `dotnet new coreex-ai` (or refreshed via
`dotnet new coreex-ai --force` / the `/coreex-docs-sync` skill). Do not hand-edit it directly —
propose the change upstream in Avanade/CoreEx instead, then refresh once it is released.
-->
# CoreEx: Validator
Guides you through creating or modifying a CoreEx validator (`Application/Validators/`) for a contract or request type. Covers declarative rules, ref-data validation, async database checks, collection and dictionary validators.
## When to Use
- New validator for a contract or request type (no database calls needed)
- New validator that requires a repository or other Application-layer dependency
- Adding property rules or an async check to an existing validator
- Nested validator for a sub-property (`.Entity()`), a collection, or a dictionary
- Switching to FluentValidation-compatible `AbstractValidator` syntax
## When Not to Use
- Domain invariants (aggregates, entities, value objects) — those belong in the Domain layer
- Infrastructure-level data checks that are not accessed via an Application-layer interface
- `FluentValidation` NuGet package — `AbstractValidator` here is `CoreEx.Validation.AbstractValidator`
## Quick Reference
**Clarifying questions to ask before writing any code:**
1. Does the validator need a constructor-injected dependency (e.g. a repository)? (determines base class)
2. Which properties need validation? (list upfront — batch type resolution, don't interrupt per-property)
3. Are any ref-data properties required? Optional? (`.Mandatory().IsValid()` vs `.IsValid()`)
4. Are any checks async (e.g. confirming an entity exists in the database)?
5. Does the user prefer FluentValidation-style `RuleFor(x => ...)` syntax?
**Base class decision:**
| Situation | Base class | Notes |
|---|---|---|
| No injection needed | `Validator<T, TSelf>` | Exposes `Default` singleton; invoke via `.Default.ValidateAndThrowAsync(...)` |
| Constructor injection needed | `Validator<T>` | No `Default`; instantiate at the call site with already-injected dependencies: `new {Name}Validator(_dep).ValidateAndThrowAsync(...)` |
| FluentValidation-style preferred | `AbstractValidator<T, TSelf>` | `RuleFor(x => ...)` / `NotEmpty()` / `IsValid()` — still CoreEx; has `Default` |
**Key rules at a glance:**
- Ref-data: `.IsValid()` on the **navigation property** (`Gender`), never on `*Code` string
- `Mandatory()` on a non-nullable value type errors on `default` (`0`, `MinValue`) — use a range rule if `0` is valid
- Runtime-computed thresholds: use delegate overloads (`.LessThanOrEqualTo(_ => ...)`) — prefer over `OnValidateAsync` imperative logic
- `context.HasErrors` guard before async I/O; `context.HasError(x => x.Prop)` for per-property guards
- `context.AddError(x => x.Prop, ...)` — member-access expression, never `nameof(...)`
- Message text argument is a `{2}` suffix substitution — not a full sentence; use `.Error("...")` to override the whole message
- **Always generate or update the matching `{Validator}Tests`** in `*.Test.Unit/Validators/` — cover conditional/business rules and cross-field logic thoroughly, plus a representative error/success pair for simple rules; skip dedicated boundary tests for framework-guaranteed constraints like length rules (`MaximumLength`/`MinimumLength`/`Length`/`String`)
For full workflow, rule reference, and code examples see [`references/workflow.md`](references/workflow.md).
## Key References
- [`/.github/instructions/coreex-validators.instructions.md`](/.github/instructions/coreex-validators.instructions.md) — full rule set, comparison operators, localization, DependsOn, DI registration
- [`/.github/instructions/coreex-tests.instructions.md`](/.github/instructions/coreex-tests.instructions.md) — validator unit test conventions: `Test.Scoped`, `AssertErrors`, expected message text
- Related skills: [`coreex-app-service`](../coreex-app-service/SKILL.md) (invokes the validator), [`coreex-policy`](../coreex-policy/SKILL.md) (async I/O guard sibling for checks a validator cannot do), [`coreex-contract`](../coreex-contract/SKILL.md) (the type being validated)
- Illustrative examples (CoreEx sample — not present in your project):
- [`ProductValidator` + `MovementRequestValidator`](https://github.com/Avanade/CoreEx/tree/main/samples/src/Contoso.Products.Application/Validators) — simple, plus injection + dictionary + async
- [Shopping validators](https://github.com/Avanade/CoreEx/tree/main/samples/src/Contoso.Shopping.Application/Validators) — `AbstractValidator` style, plain request validators
- [`OrderValidator`](https://github.com/Avanade/CoreEx/tree/main/samples/src/Contoso.Orders.Application/Validators) — collection validator
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!