Minimal APIs - Usando parameter binding


  Aproveite o recurso parameter binding na ASP.NET Core 7 para converter dados do request em parâmetros fortemente tipados.

Se você não sabe o que são as minimal APIs, elas são um tipo de API na ASP.NET Core que inclui um mínimo de arquivos, recursos e dependências e que permitem que criar endpoints REST totalmente funcionais com codificação e configuração mínimas.

Um dos novos recursos da ASP.NET Core 7 é o suporte para associação de parâmetros ou parameter binding nas APIs mínimas que veremos a seguir. Antes vamos apresentar o conceito.

O que é a vinculação de parâmetros?

A vinculação de parâmetros envolve o mapeamento de dados do request HTTP de entrada para parâmetros de métodos Actions, permitindo que os desenvolvedores processem requisições e respondam de maneira estruturada e eficiente.

Ao receber uma request HTTP, a ASP.NET Core examina os valores dos cabeçalhos, do corpo e da URL do request para determinar os valores dos parâmetros do método de controle correspondente e tenta associar automaticamente os valores dos parâmetros HTTP com os parâmetros do método de controle com base em seus nomes e tipos.

Por exemplo, se um método de controle espera um parâmetro chamado id, o framework tentará extrair o valor do parâmetro id da URL do request. Se o método de controle espera um parâmetro complexo, como um objeto JSON, ele tentará analisar o corpo da solicitação e desserializá-lo em um objeto do tipo apropriado.

Com a associação de parâmetros, os desenvolvedores não precisam mais escrever código para extrair valores de cabeçalhos, URL ou body do request HTTP. A ASP.NET Core faz todo o trabalho pesado automaticamente, permitindo que os desenvolvedores se concentrem na lógica de negócios de seus aplicativos.

Na ASP.NET Core 7 as minimal APIs oferecem vários tipos de associação de parâmetros, incluindo FromQuery, FromRoute, FromHeader e FromBody.

Por que usar a vinculação de parâmetros?

Aqui estão alguns motivos pelos quais você deve usar a vinculação de parâmetros nas APIs mínimas.

1- Para simplificar o código: Usando a vinculação de parâmetros, você pode reduzir o código repetido necessário para lidar com as solicitações HTTP recebidas. Em vez de analisar manualmente os parâmetros da string de consulta, rotear dados e corpos de solicitação, a vinculação de parâmetros permite que você defina os parâmetros do método Action e faça com que a estrutura trate com o processo de vinculação automaticamente.

2- Para melhorar a capacidade de manutenção do código: Ao aproveitar a vinculação de parâmetros nas APIs mínimas, você pode criar um código mais sustentável, mais fácil de entender e modificar ao longo do tempo. O processo de vinculação é padronizado e previsível, tornando mais fácil para os desenvolvedores entender como os dados são transmitidos entre o cliente e o servidor.

3- Para aprimorar o desempenho do aplicativo: A associação de parâmetros também pode ajudar a melhorar o desempenho reduzindo o processamento de dados desnecessário no aplicativo. Por exemplo, vinculando um body do request o a um tipo de parâmetro específico, o framework pode evitar a sobrecarga de análise e desserialização de todo o corpo da solicitação, concentrando-se apenas nos dados relevantes necessários ao aplicativo.

4- Para lidar com tipos de dados complexos: A vinculação de parâmetros pode ser usada para lidar com tipos de dados complexos, como objetos aninhados, arrays e coleções. Aproveitando os mecanismos integrados para vincular tipos de dados complexos, você pode criar APIs que abordam uma ampla variedade de formatos de dados sem precisar escrever código adicional.

Como funciona a vinculação de parâmetros?

A associação de parâmetros funciona de maneira semelhante aos aplicativos ASP.NET Core tradicionais. Quando um cliente faz uma solicitação HTTP para uma minimal API,  os dados da solicitação são mapeados automaticamente para os parâmetros do método de ação com base nos nomes e tipos de parâmetro.

Por padrão, o framework usa uma abordagem baseada em convenções para mapear automaticamente os dados da solicitação para os parâmetros dos métodos Action, mas você também podem usar a vinculação explícita de parâmetros para obter mais controle sobre esse processo.

Vinculação de parâmetro com strings de consulta

Para usar a associação de parâmetros você precisa definir métodos Action que aceitem parâmetros. Por exemplo, o trecho de código a seguir define um endpoint de API mínimo que aceita um parâmetro da string de consulta.

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/Ola", ([FromQuery] string nome) =>
{
  
return $"Olá {nome}";
});

app.Run();

Neste exemplo, o atributo [FromQuery] instrui a estrutura a vincular o parâmetro name ao valor do parâmetro de string de consulta name na solicitação HTTP.

Vinculação de parâmetro com injeção de dependência

Com a ASP.NET Core 7, você pode aproveitar a injeção de dependência para vincular parâmetros nos métodos Action de seus controladores de API. Se o tipo estiver configurado como um serviço, não será mais necessário adicionar o atributo [FromServices] aos parâmetros do método. Considere o trecho de código a seguir. 

[Route("[controller]")]
[ApiController]

public
class DemoController : ControllerBase
{
  
public ActionResult Get(IDateTime dateTime) => Ok(dateTime.Now);
}

Se o tipo for configurado como um serviço, você não precisa usar o atributo [FromServices] para vincular parâmetros. Em vez disso, você pode usar o seguinte trecho de código para vincular parâmetros usando injeção de dependência.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<IDateTime, SystemDateTime>();

var app = builder.Build();

app.MapGet("/", (IDateTime dateTime) => dateTime.Now);
app.MapGet(
"/demo", ([FromServices] IDateTime dateTime) => dateTime.Now);

app.Run();

Vinculação explícita de parâmetros em APIs mínimas

A associação de parâmetro explícito é uma técnica que permite ter mais controle sobre o processo de associação, especificando explicitamente a origem dos dados para um determinado parâmetro.

Isso é útil em situações em que o comportamento de vinculação não pode ser inferido apenas pelo nome ou tipo do parâmetro. Nas APIs mínimas da ASP.NET Core 7, podemos  usar os seguintes atributos para especificar explicitamente a fonte de dados para um parâmetro:

[FromQuery] - Define que o valor do parâmetro deve ser derivado da string de consulta HTTP.
[FromRoute] - Especifica que o valor do parâmetro deve ser derivado dos dados de rota da solicitação HTTP.
[FromHeader] - Define que o valor do parâmetro deve ser obtido do cabeçalho da solicitação HTTP.
[FromBody] - Especifica que o valor do parâmetro deve vir do corpo da solicitação HTTP.

Por exemplo, considere o seguinte endpoint mínimo de API que aceita uma instância do tipo Autor no body do request:

app.MapPost("/demo", ([FromBody] Autor author) =>
{
  
// lógica para processar os dados
});

Nesse caso, o atributo [FromBody] instrui o framework a vincular o parâmetro aos dados no corpo do request. Se esse atributo não for especificado, o framework tentará vincular o parâmetro usando outras fontes disponíveis, como string de consulta ou dados de rota, o que provavelmente não é o que queremos neste cenário.

Observe que você também pode usar o atributo [AsParameters] para mapear parâmetros de consulta diretamente para um objeto sem precisar usar os métodos BindAsync ou TryParse.

app.MapGet("/exibir", ([AsParameters] Autor autor) =>
{
  
return $"Nome: {autor.Nome}, Email: {autor.Email}";
});

Associação de modelo personalizado em APIs mínimas

A vinculação de modelo personalizada permite definir sua própria lógica de vinculação para tipos de dados complexos ou cenários que não podem ser manipulados pelos mecanismos de vinculação padrão. A vinculação customizada é particularmente útil ao trabalhar com APIs que requerem transformação ou normalização de dados antes que os dados possam ser usados pelo aplicativo.

Nas APIs mínimas da ASP.NET Core 7, a vinculação de modelo personalizada é obtida implementando a interface IModelBinder ou usando a interface IModelBinderProvider para fornecer uma implementação personalizada da interface IModelBinder para um tipo de dados específico.

Para criar um associador de modelo personalizado, você precisa implementar a interface IModelBinder e substituir o método BindModelAsync. Esse método usa um parâmetro BindingContext, que contém informações sobre o request e o modelo que está sendo vinculado.

No método BindModelAsync, você pode executar qualquer transformação ou validação de dados necessária antes de retornar o modelo vinculado.

A seguir  temos um exemplo de um associador de modelo personalizado que vincula uma carga útil JSON recebida a um objeto Cliente.

public class ClienteModelBinder : IModelBinder
{
 
public async Task BindModelAsync(ModelBindingContext bindingContext)
  {
   
var json = await new StreamReader(bindingContext.HttpContext.Request.Body).
                ReadToEndAsync();

     var cliente = JsonSerializer.Deserialize<Cliente>(json);
     bindingContext.Result = ModelBindingResult.Success(cliente);
  }
}

Neste exemplo, a classe ClienteModelBinder implementa a interface IModelBinder e fornece uma implementação personalizada do método BindModelAsync. O método lê a carga JSON do corpo da solicitação HTTP e a desserializa em um objeto Cliente usando a biblioteca System.Text.Json. O objeto Cliente resultante é retornado como um ModelBindingResult bem-sucedido.

Para usar esse associador de modelo personalizado em um endpoint de API mínimo, você pode usar o atributo [ModelBinder] no parâmetro.

app.MapPost("/cliente", ([ModelBinder(typeof(ClienteModelBinder))] Cliente cliente) =>
{
  
//código
});

No exemplo de código anterior, o atributo [ModelBinder] especifica que o parâmetro Cliente deve ser associado usando a classe ClienteModelBinder.

A vinculação de parâmetros simplifica a gravação de código para lidar com solicitações HTT  e permite manipular mais facilmente tipos de dados complexos, simplificando o código e melhorando a capacidade de manutenção do código, enquanto cria a lógica dos endpoints da sua API

E estamos conversados ..

"Não tenhas inveja dos homens malignos, nem desejes estar com eles.
Porque o seu coração medita a rapina, e os seus lábios falam a malícia."
Provérbios 24:1-2

Referências:


José Carlos Macoratti