Appearance
GrydBaseController
GrydBaseController centraliza o contrato HTTP para controllers que usam Result/Result<T>.
Comportamento padrão
- Sucesso com
Result<T>:200 OKcom payload direto (T). - Sucesso com
Result:200 OKsem 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:errorCodede 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);
}