agentleFS
LeanMeanCleanAppsLeanMeanCleanApps/CleanMinimalApi/.agents/skills/expose-a-use-case/SKILL.md

expose-a-use-case

Skill400 starsChanged 10 days agoMITView on GitHub

How to put an Application use case on a Minimal API endpoint - endpoint groups, static handler methods, TypedResults, Produces metadata, XML docs for Scalar, JSON source generation and tests. Use when adding or changing an endpoint in this Minimal API.

4 other projects use a version of this, 1 of them edited.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

9 rules. 0 are common, 0 are distinctive, and 9 are very specific to this project.

  • 0

    Common

    Most of the 4 edited versions we read keep these.

  • 0

    Distinctive

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Add the use case first (add-a-use-case).

    line 16
  2. Very specific:

    Write the handler method: [FromRoute], [FromQuery] and [FromBody] on every input, [FromServices] ISender sender, then CancellationToken …

    line 28
  3. Very specific:

    Add every new request or response type to AppJsonSerializerContext (src/Presentation/Serialization/) with [JsonSerializable(typeof(...))], …

    line 31
  4. Very specific:

    Document the method: <summary> (short, title case, shown as the operation name), <remarks> with a sentence or two and a sample request, …

    line 32
  5. Very specific:

    Add a sample request for the endpoint to src/Presentation/Presentation.http.

    line 34
  6. Very specific:

    Test it twice: a unit test calling the static method with a faked ISender (tests/Presentation.Tests.Unit/Endpoints/), and an integration …

    line 35
  7. Very specific:

    Use Results.Ok(...) or return IResult.

    line 59
  8. Very specific:

    Document the sender parameter (xml-docs-and-openapi).

    line 61
  9. Very specific:

    Put a route's group-level settings (RequireAuthorization, WithTags) on single endpoints.

    line 63

“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Expose a use case (Minimal API)

The rule

Endpoints live in src/Presentation/Endpoints/<Feature>Endpoints.cs, one static class per resource. A Map<Feature>Endpoints extension maps a route group; each endpoint is a public static async method that builds the Application request, sends it through ISender and returns a TypedResults value. The method's XML comments become the operation's documentation in Scalar. Endpoints contain no logic: validation, not-found and everything else happen in Application, and ApplicationExceptionHandler turns exceptions into problem details.

Steps

  1. Add the use case first (add-a-use-case).
  2. In the feature's endpoints class, map the route on the group and describe every response:

    _ = root.MapGet("/{id:guid}", GetReviewById)
        .WithName(nameof(GetReviewById))
        .Produces<Entities.Review>()
        .ProducesValidationProblem()
        .ProducesProblem(StatusCodes.Status404NotFound)
        .ProducesProblem(StatusCodes.Status500InternalServerError);
  3. Write the handler method: [FromRoute], [FromQuery] and [FromBody] on every input, [FromServices] ISender sender, then CancellationToken cancellationToken. Optional query parameters with defaults go last.
  4. Return the narrowest TypedResults type: Ok<T>, CreatedAtRoute<T> (with the by-id route name) for creates, NoContent for updates and deletes.
  5. Bodies use a request class in src/Presentation/Requests/ with XML docs and <example> values. Map it to the command in the endpoint.
  6. Add every new request or response type to AppJsonSerializerContext (src/Presentation/Serialization/) with [JsonSerializable(typeof(...))], including Page<T> and List<T> forms (json-serialization).
  7. Document the method: <summary> (short, title case, shown as the operation name), <remarks> with a sentence or two and a sample request, <param> for each input except sender and the token, and a <response code="..."> for each status.
  8. A new endpoints class is mapped in WebApplicationExtensions.ConfigureApplication under #region MinimalApi.
  9. Add a sample request for the endpoint to src/Presentation/Presentation.http.
  10. Test it twice: a unit test calling the static method with a faked ISender (tests/Presentation.Tests.Unit/Endpoints/), and an integration test making the real request (tests/Presentation.Tests.Integration/Endpoints/, see presentation-integration-tests). Cover every documented status code (test-design).

Example

// src/Presentation/Endpoints/ReviewEndpoints.cs
public static async Task<CreatedAtRoute<Entities.Review>> CreateReview(
    [FromBody] CreateReviewRequest request,
    [FromServices] ISender sender,
    CancellationToken cancellationToken)
{
    var response = await sender.Send(new Commands.CreateReview.CreateReviewCommand
    {
        AuthorId = request.AuthorId,
        MovieId = request.MovieId,
        Stars = request.Stars
    }, cancellationToken);

    return TypedResults.CreatedAtRoute(response, nameof(GetReviewById), new { id = response.Id });
}

Don't

  • Use Results.Ok(...) or return IResult. TypedResults with a concrete return type gives OpenAPI the real response type.
  • Catch exceptions or check null in an endpoint.
  • Document the sender parameter (xml-docs-and-openapi).
  • Forget [JsonSerializable] for a new type; serialization then falls back to reflection.
  • Put a route's group-level settings (RequireAuthorization, WithTags) on single endpoints.

Check

dotnet test tests/Presentation.Tests.Unit
dotnet test tests/Presentation.Tests.Integration
dotnet run --project ./src/Presentation   # then read the endpoint at http://localhost:7310/scalar

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.