| name | coreex-app-service |
| description | Create or modify a CoreEx Application-layer service. USE FOR: new service class (exception-based or Result<T>), adding CRUD/business operations, CQRS read service (XxxReadService), adapter interface in Application/Adapters/, policy class in Application/Policies/, application-level mapper (Domain → Contract). DO NOT USE FOR: Infrastructure repositories (use coreex-repository), validators (use coreex-validator), controller endpoints (use coreex-api). |
| argument-hint | Optional: entity name, operations needed (get/create/update/delete/query/custom), exception-based or Result<T> pipeline, cross-domain calls needed |
| tags | ["application-service","application-layer","unit-of-work","cqrs","events","adapter","policy","result","coreex"] |
CoreEx: Application Service
Guides you through creating or modifying a CoreEx Application-layer service in Application/. Covers CRUD operations, business actions, unit-of-work + events, CQRS read services, adapters, and policies.
When to Use
- New service class for an entity (scaffold interface + implementation)
- Adding a mutation operation (create / update / delete / custom business action)
- Adding a CQRS read service (
{Name}ReadService) for queries and read-model shapes
- Adding an adapter interface (
Application/Adapters/) for a cross-domain or external-service call
- Adding a policy class (
Application/Policies/) for guard logic that requires I/O
- Switching a method between exception-based and
Result<T> pipeline styles
When Not to Use
- Infrastructure repositories — use the
coreex-repository skill
- Validators — use the
coreex-validator skill
- Controller endpoints — use
coreex-api
- Domain aggregates, entities, value objects — those belong in the Domain layer
Quick Reference
Clarifying questions before writing any code:
0. Resolve rop-enabled (exception vs Result<T>), whether a *.Domain project exists (aggregate mapping vs direct-CRUD), and outbox-enabled (event publishing) from the solution-root AGENTS.md Feature Configuration and project structure before asking the rest; only prompt for what is unresolved and re-state resolved values for confirmation.
- Exception-based or
Result<T> pipeline style? (→ Path A or B — per-project choice)
- Which operations? Get / Create / Update / Delete / custom business action? (never assume Query)
- Any cross-domain or external-service calls? (→ adapter interface, Path D)
- Any policy guard checks requiring I/O? (→ policy class, Path D)
- Domain layer present? (→
Application/Mapping/ mapper; used in Path B)
- Read-only queries or collection results needed? (→ CQRS read service, Path C)
Key rules at a glance:
[ScopedService<IInterface>] on every service — auto-registers via AddDynamicServicesUsing<T>()
- Only inject: repository, unit of work, adapter interfaces, logger — never validators, mappers, policies
ValidateAndThrowAsync (exception style) / ValidateWithResultAsync (Result<T>) — never bare ValidateAsync
- Service assigns
Id after validation: value.Id = Runtime.NewId() (string key) / Runtime.NewGuid() (Guid)
- All mutations in
_unitOfWork.TransactionAsync(...) — event added inside, never outside
WhereMutated(v => ...) for Create/Update (DataResult<T> carries value); WhereMutated(() => ...) for Delete
- Delete event:
EventData.CreateEvent<T>(EventAction.Deleted).WithKey(id) — no value body
NotFoundException.ThrowIfDefault(entity) after any Get that must find the entity
- Validators / Mappers / Policies: not DI-registered — call or instantiate at point of use
Validator<T, TSelf>: call via singleton — {Name}Validator.Default.ValidateAndThrowAsync(...)
Validator<T> (with injection): instantiate at call site — new {Name}Validator(_dep).ValidateAndThrowAsync(...)
- All interface methods include
CancellationToken cancellationToken = default as the last parameter; pass through to every async call and TransactionAsync(async ct => ..., cancellationToken)
- CQRS: mutations +
GetAsync → {Name}Service; queries + GetAsync → {Name}ReadService (both have GetAsync)
- Always
.ConfigureAwait(false) on every await
For full workflow and code examples see references/workflow.md.
Key References
/.github/instructions/coreex-application-services.instructions.md — full conventions: guard clauses, events, CQRS, adapters, policies, Result<T> operators
- Related skills:
coreex-repository (persistence the service injects), coreex-validator (invoked before mutations), coreex-policy (I/O guard logic), coreex-adapter (cross-domain calls), coreex-contract (the entity/request types), coreex-aggregate (Domain layer + mapping), coreex-api (consumes the service), coreex-test-api (tests the service through the host)
- Application layer deep-dive — optional (after
/coreex-docs-sync)
- Illustrative examples (CoreEx sample — not present in your project):