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

expose-a-use-case

Skill4 starsChanged 10 days agoMITView on GitHub

How to put an Application use case on a Web API controller action - controllers on ApiControllerBase, the injected ISender, ActionResult return types, ProducesResponseType metadata, XML docs for Scalar and integration tests. Use when adding or changing an action in this Web 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

6 rules. 0 are common, 0 are distinctive, and 6 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.

  • 6

    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:

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

    line 28
  3. Very specific:

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

    line 29
  4. Very specific:

    Test it with real requests in tests/Presentation.Tests.Integration/Controllers/<Feature>EndpointTests.cs (presentation-integration-tests).

    line 30
  5. Very specific:

    Put [Produces] on the base class.

    line 61
  6. Very specific:

    Put [Authorize] on single actions.

    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 (Web API)

The rule

Controllers live in src/Presentation/Controllers/<Feature>/<Feature>Controller.cs, one per resource, and inherit ApiControllerBase. The base class carries [ApiController], [Consumes("application/json")] and, in a solution with authentication, [Authorize], and takes the ISender through its constructor. Each action builds the Application request, sends it with this.Sender and returns an ActionResult. The action's XML comments become the operation's documentation in Scalar. Actions 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. A new controller takes the sender in its primary constructor and passes it on:

    [Route("api/reviews")]
    public class ReviewsController(ISender sender) : ApiControllerBase(sender)
  3. Give each action its verb and route template, [EndpointName(nameof(...))], and one [ProducesResponseType] per status with its content type: application/json for success bodies, application/problem+json for errors, none for 204.
  4. Parameters: route values by name (Guid id), [FromQuery] on query values, the body as a request class, then CancellationToken cancellationToken. Optional query parameters with defaults go last.
  5. Return ActionResult<T> for actions with a body and IActionResult for 204. Use this.Ok(...), this.CreatedAtAction(nameof(this.GetReviewById), new { id = response.Id }, response) for creates, and this.NoContent() for updates and deletes.
  6. Bodies use a request class in Controllers/<Feature>/Requests/ with XML docs and <example> values. Map it to the command in the action.
  7. Document the action: <summary> (short, title case, shown as the operation name), <remarks> with a sentence or two and a sample request, <param> for each input except the token, and a <response code="..."> for each status.
  8. Add a sample request for the action to src/Presentation/Presentation.http.
  9. Test it with real requests in tests/Presentation.Tests.Integration/Controllers/<Feature>EndpointTests.cs (presentation-integration-tests). Cover every documented status code (test-design).

Example

// src/Presentation/Controllers/Reviews/ReviewsController.cs
[HttpPost]
[EndpointName(nameof(CreateReview))]
[ProducesResponseType(typeof(Entities.Review), StatusCodes.Status201Created, "application/json")]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest, "application/problem+json")]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound, "application/problem+json")]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError, "application/problem+json")]
public async Task<ActionResult<Entities.Review>> CreateReview(CreateReviewRequest request, CancellationToken cancellationToken)
{
    var command = new Commands.CreateReview.CreateReviewCommand
    {
        AuthorId = request.AuthorId,
        MovieId = request.MovieId,
        Stars = request.Stars
    };

    var response = await this.Sender.Send(command, cancellationToken);

    return this.CreatedAtAction(nameof(this.GetReviewById), new { id = response.Id }, response);
}

Don't

  • Resolve services from HttpContext.RequestServices. Take them through the constructor.
  • Catch exceptions, check null or read ModelState in an action. [ApiController] and the exception handler do that.
  • Put [Produces] on the base class. It adds an empty JSON body to 204 responses; set the content type on each [ProducesResponseType] instead.
  • Return an entity without this.Ok(...). Keep every action's result explicit.
  • Put [Authorize] on single actions. With authentication the base class protects everything and [AllowAnonymous] is the exception; without it there's nothing to protect (optional-token-auth).

Check

dotnet test tests/Presentation.Tests.Integration
dotnet run --project ./src/Presentation   # then read the action at http://localhost:7340/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.