Every layer the DKNet 10.1.14 generators can produce is declared, not written:
[RaisesEvent]for events,[CrudCreate]/[CrudUpdate]/[CrudAction]+[GenerateDto]for the generated request/handler/route/DTO shapes.
This sample declares behavior through attributes instead of writing it by hand. It shows:
Product aggregate whose creation and price-change events are declared by attribute; no
AddEvent call appears anywhere in this sample.[CrudCreate] constructor and
a [CrudUpdate] method.[CrudAction] methods — Approve published at an explicit
route segment on the default verb, and Discontinue on an overridden one — so the sample shows
both the default and the override without you inventing one. Neither has a hand-written request,
handler or endpoint registration.For the line-by-line trade-off against the manual sample, including the confirmed validation gap
this sample carries, see docs/samples/manual-vs-automated.md.
Base path /v1/products, generated by MapProductCrud():
| Route | Notes |
|---|---|
POST / |
No idempotency protection and no enforced validation — see the comparison doc. |
GET / |
Generic list (DKNet.AspCore.Extensions’ MapGetList) with the uniform filter/search/orderBy/desc/pageNumber/pageSize contract, resolved against ProductDto — see docs/generic-list-endpoint.md. |
GET /{id} |
404 on unknown id (generic MapGetById). |
PUT /{id} |
Changes Price; 404 on unknown id. |
DELETE /{id} |
Generic MapDeleteById. |
POST /{id}/approval |
Domain action — [CrudAction("approval")] Approve(string byUser). Body { "byUser": "..." }; 200 + ProductDto; 404 on unknown id. |
PUT /{id}/discontinue |
Domain action on an overridden verb — [CrudAction(Verb = CrudActionVerb.Put)] Discontinue(). No body; 200 + ProductDto. A no-op 200 on an already-discontinued product — a generated action has nowhere to hang a pre-condition. |
External broker publish/subscribe — a ProductCreatedEvent, raised purely by
[RaisesEvent] declaration, is produced to the product-tp Azure Service Bus topic and consumed
by ProductCreatedNotificationHandler on the product-sub subscription.
Generated domain actions — Approve and Discontinue are declared as [CrudAction] methods
on the entity and published as routes with no per-action code. Approve keeps its acting user as
a method parameter, so the generated request exposes it as caller-supplied — that is this
sample’s own long-standing choice, unchanged by the actions. See
docs/crud-attributes.md for how to
declare your own.
It does not carry request idempotency or static seed data; see the manual sample for those.
Its forwarded [Range] validation on Price is never evaluated under this template’s own
endpoint-registration convention. Confirmed live: POST /v1/products with a negative price returns
201, not 400. Read why in the comparison doc before reusing this pattern for an entity whose
validation must actually be enforced.
Remove src/ApiEndpoints/**/AutomatedSample/**, src/ApiEndpoints/Minimal.Api/ApiEndpoints/AutomatedSample/,
the two Produce<ProductCreatedEvent>/Consume<ProductCreatedEvent> lines in
Minimal.Infra/Extensions/ServiceBusSetup.cs, and this docs/samples/automated-products/ folder.
Then drop its EF Core mapping from the next migration. No other feature depends on it.