NET 7 -  Mininal APIs : Array Binding e Ler Stream do Request


   Hoje veremos dois novos recursos das Minimal Apis no .NET 7 : Array binding e a leitura de stream do body do request.

Embora seja muito simples, o recurso array binding permite anexar múltiplos valores em uma query string que serão capturados e inseridos em um array de strings.

Exemplo:

// GET /procurar?id=1&id=4&id=7

app.MapGet("/procurar", (int[] ids) =>
     
$"Artigo Ids: {ids[0]}, {ids[1]}, {ids[2]}");

 

Além disso, podemos usar o atributo [AsParameters] para mapear automaticamente os parâmetros de consulta em um objeto, sem a necessidade de mapeamento personalizado com BindAsync ou TryParse.


app.MapGet(
"/procurar", ([AsParameters] Livro info) =>
{
  
return $"Livro: {info.Autor}, Ano: {info.Ano}";
});
 

O outro recurso é que agora podemos ler o body do request como um stream e fazer o que quiser.

Como exemplo vamos criar uma minimal API no VS 2022 preview para ilustrar.

Recursos usados :

Criando o projeto no VS 2022

Abra o VS 2022 preview e clique em Create a New Project selecionando o template ASP.NET Core Web API” :

Informe o nome MinApi_NovosRecursos;

A seguir defina as demais configurações conforme mostrada na imagem a seguir:

Ao clicar em Create teremos a minimal API criada.

Vamos alterar o código gerado pelo template criando um novo endpoint onde vamos mapear um array de nomes recebidos via QueryString :

app.MapGet("/procurar", (string[] nomes) =>
{
  
var result= $"Nomes : {nomes[0]}, {nomes[1]}, {nomes[2]}";
   return
Results.Ok(result);
});
 

A seguir vamos criar outro endpoint onde vamos usar o atributo [AsParameters] para mapear automaticamente os parâmetros de consulta em um objeto definido como um tipo. No exemplo definimos a classe Livro.


app.MapGet(
"/buscar", ([AsParameters] Livro info) =>

  
return $"Livro: {info.Autor}, Ano: {info.Ano}";
});
 

Aqui estamos usando a classe Livro definida conforme abaixo:

public class Livro
{
    public string? Autor { get; set; }
    public int Ano { get; set; }  
}

Para concluir vamos incluir mais um endpoint agora usando o novo recurso que permite ler o corpo do request como um stream :

app.MapPost("streams", async (Stream body) =>
{
     string tempfile = CreateTempfilePath();
     using var stream = File.OpenWrite(tempfile);
     await body.CopyToAsync(stream);
});

 

Lembrando que este stream é somente leitura e não armazenado em buffer, o que significa que só pode ser lido uma vez.

Aqui estamos usando o método CreateTempFilePath() que define o nome do arquivo e o local no servidor para armazenar o arquivo binário :

static string CreateTempfilePath()
{
    var filename = $@"{DateTime.Now.Ticks}.tmp";

    var directoryPath = Path.Combine("temp", "uploads");

    if (!Directory.Exists(directoryPath))
        Directory.CreateDirectory(directoryPath);

     return Path.Combine(directoryPath, filename);
}

Executando o projeto teremos os endpoints exibidos no Swagger:

1- Acionando o endoint GET /procurar que esperar receber 3 strings e obter um array de strings :

Informando duas strings : Maria, Soares e Sanches ao clicar em Execute teremos o resultado:

1- Acionando o endoint GET /buscar onde usamos o atributo [AsParameters] :

Informamos o nome do Autor : Macoratti e o Ano como 2022 e ao clicar em Execute teremos:

Para testar o último endpoint vamos usar o Postman.

Abrindo o Postman e acionando o endpoint : POST https://localhost:7202/streams

A seguir vamos selecinar Body depois binary e vamos selecionar um arquivo binário. Clicando em Send obtemos o retorno 200 OK.

Como não fizemos nenhum tratamento o arquivo será enviado para a pasta Debug/net7.0

Temos assim 3 novos recursos das Minimal APis no .NET 7.0 que podem nos auxiliar na criação de nossos projetos...

Pegue o projeto aqui : MinApi_NovosRecuros.zip

"Vai alta a noite, e vem chegando o dia. Deixemos, pois, as obras das trevas e revistamo-nos das armas da luz.
Andemos dignamente, como em pleno dia, não em orgias e bebedices, não em impudicícias e dissoluções, não em contendas e ciúmes; mas revesti-vos do Senhor Jesus Cristo e nada disponhais para a carne no tocante às suas concupiscências."

Romanos 13:12-14

Referências:


José Carlos Macoratti