Skip to content

GrydBaseController

GrydBaseController centraliza o contrato HTTP para controllers que usam Result/Result<T>.

Comportamento padrão

  • Sucesso com Result<T>: 200 OK com payload direto (T).
  • Sucesso com Result: 200 OK sem envelope de sucesso.
  • Falha: ProblemDetails (RFC 7807) com shape único.

Shape de erro

Todos os erros retornam application/problem+json:

json
{
  "status": 404,
  "title": "Not Found",
  "detail": "User not found",
  "type": "https://gryd.io/errors/not-found",
  "instance": "/api/v1/users/...",
  "traceId": "...",
  "code": "USER_NOT_FOUND",
  "errors": ["User not found"]
}

Campos em extensions:

  • traceId: sempre presente.
  • code: errorCode de domínio (quando disponível).
  • errors: lista detalhada (quando disponível).

Mapeamento de status por errorCode

O roteamento HTTP é baseado em sufixos de errorCode:

  • _NOT_FOUND -> 404
  • _ALREADY_EXISTS, _ALREADY_ASSIGNED, _CONFLICT -> 409
  • _FORBIDDEN, _ACCESS_DENIED -> 403
  • _UNAUTHORIZED -> 401
  • _UNPROCESSABLE -> 422
  • sem sufixo reconhecido -> 400

Principais helpers

  • ToActionResult(Result)
  • ToActionResult<T>(Result<T>)
  • ToErrorActionResult(Result)
  • ToErrorActionResult<T>(Result<T>)
  • ToCreatedResult<T>(Result<T>, actionName, routeValues)
  • NotFoundResult(message, errorCode?, errors?)
  • ForbiddenResult(message?, errorCode?, errors?)
  • ConflictResult(message, errorCode?, errors?)
  • UnprocessableResult(message, errorCode?, errors?)

Exemplo

csharp
[HttpPost]
public async Task<IActionResult> Create(CreateUserCommand command, CancellationToken ct)
{
    var result = await _mediator.Send(command, ct);
    return ToCreatedResult(result, nameof(GetById), new { id = result.Data!.Id });
}

[HttpGet("{id:guid}")]
public async Task<IActionResult> GetById(Guid id, CancellationToken ct)
{
    var result = await _mediator.Send(new GetUserByIdQuery(id), ct);
    return ToActionResult(result);
}

Released under the MIT License.