Implementando Consultas Específicas em Web API com C# .NET

Aprenda a criar endpoints específicos em sua Web API ASP.NET Core para filtrar e buscar dados de forma precisa. Neste guia, mostro como implementar endpoints personalizados além do GET tradicional.

Por que Endpoints Específicos?

Vantagens dos Endpoints Personalizados

  • Busca precisa: Filtros específicos por código, nome ou descrição
  • Performance: Retorna apenas os dados necessários
  • Flexibilidade: Diferentes critérios de busca
  • Experiência do consumidor: API mais intuitiva

Implementando GET com Filtro

Endpoint para Buscar por Descrição

[HttpGet("byDescription")]
public ActionResult<WeatherForecast> GetByDescription(string description)
{
    try
    {
        // Simulando busca em banco de dados
        var foundItem = summaries.FirstOrDefault(s => 
            s.Contains(description, StringComparison.OrdinalIgnoreCase));

        if (foundItem == null)
            return NotFound($"Nenhum item encontrado com a descrição: {description}");

        // Retornando objeto mock (na prática, viria do banco)
        return Ok(new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = foundItem
        });
    }
    catch (Exception ex)
    {
        return StatusCode(500, $"Erro interno: {ex.Message}");
    }
}

Endpoint para Buscar por Código

Implementação com Parâmetro de Rota

[HttpGet("byCode/{code}")]
public ActionResult<WeatherForecast> GetByCode(int code)
{
    try
    {
        // Simulando busca por código (ID)
        // Na prática, isso viria do banco de dados
        if (code <= 0 || code > summaries.Length)
            return NotFound($"Nenhum item encontrado com código: {code}");

        return Ok(new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(code)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = summaries[code - 1]
        });
    }
    catch (Exception ex)
    {
        return StatusCode(500, $"Erro interno: {ex.Message}");
    }
}

Tratamento de Erros e Respostas Adequadas

Códigos HTTP Appropriados

// 200 OK - Quando encontra o item
return Ok(item);

// 404 Not Found - Quando não encontra
return NotFound($"Item com código {code} não encontrado");

// 400 Bad Request - Quando parâmetros são inválidos
return BadRequest("Código inválido");

// 500 Internal Server Error - Para erros inesperados
return StatusCode(500, "Erro interno do servidor");

Melhores Práticas para Endpoints

1. Nomenclatura Consistente

// ✅ Recomendado
[HttpGet("byDescription")]
[HttpGet("byCode/{code}")]
[HttpGet("byName/{name}")]

// ❌ Evitar
[HttpGet("getItem")]
[HttpGet("search")]

2. Documentação com XML Comments

/// <summary>
/// Busca previsão do tempo por descrição
/// </summary>
/// <param name="description">Texto para busca na descrição</param>
/// <returns>Objeto WeatherForecast correspondente</returns>
/// <response code="200">Retorna o item encontrado</response>
/// <response code="404">Item não encontrado</response>
/// <response code="500">Erro interno do servidor</response>
[HttpGet("byDescription")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]

3. Validação de Parâmetros

[HttpGet("byDescription")]
public ActionResult<WeatherForecast> GetByDescription(
    [Required][MinLength(2)] string description)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);

    // Resto da implementação...
}

Exemplo Completo com Entity Framework

Busca com Banco de Dados Real

[HttpGet("byDescription")]
public async Task<ActionResult<WeatherForecast>> GetByDescription(string description)
{
    try
    {
        var forecast = await _context.WeatherForecasts
            .FirstOrDefaultAsync(f => f.Summary.Contains(description));

        if (forecast == null)
            return NotFound();

        return Ok(forecast);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Erro ao buscar previsão por descrição");
        return StatusCode(500, "Erro interno do servidor");
    }
}

Testando os Endpoints com Swagger

Exemplo de Teste

  1. Execute a aplicação
  2. Acesse /swagger
  3. Expanda o endpoint GET /WeatherForecast/byDescription
  4. Clique em “Try it out”
  5. Insira um valor no parâmetro description
  6. Execute e veja o resultado

Exemplo de Resposta

{
  "date": "2024-01-15",
  "temperatureC": 25,
  "temperatureF": 77,
  "summary": "Warm"
}

Dicas de Performance

1. Paginação para Listas Grandes

[HttpGet("search")]
public async Task<ActionResult<IEnumerable<WeatherForecast>>> Search(
    string term, int page = 1, int pageSize = 10)
{
    var query = _context.WeatherForecasts
        .Where(f => f.Summary.Contains(term))
        .Skip((page - 1) * pageSize)
        .Take(pageSize);

    return await query.ToListAsync();
}

2. Cache para Buscas Frequentes

[HttpGet("byCode/{code}")]
[ResponseCache(Duration = 300)] // Cache de 5 minutos
public async Task<ActionResult<WeatherForecast>> GetByCode(int code)
{
    // Implementação...
}

3. Logging para Monitoramento

private readonly ILogger<WeatherForecastController> _logger;

public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
    _logger = logger;
}

[HttpGet("byDescription")]
public ActionResult<WeatherForecast> GetByDescription(string description)
{
    _logger.LogInformation("Buscando por descrição: {Description}", description);
    // Implementação...
}

Conclusão

Endpoints específicos transformam sua API de genérica para poderosa:

✅ Benefícios Implementados

  • Busca precisa com filtros customizados
  • Melhor performance retornando apenas dados necessários
  • Experiência melhor para consumidores da API
  • Código mais organizado e maintainable

🚀 Próximos Passos

  1. Implementar autenticação nos endpoints
  2. Adicionar rate limiting
  3. Criar documentação detalhada
  4. Implementar versionamento da API

Pronto para implementar endpoints específicos na sua API? Comece com um endpoint simples e gradualmente adicione complexidade conforme needed!

Baseado em implementações reais de APIs RESTful com ASP.NET Core e Entity Framework.