.NET 6 - ASP .NET Core - Minimal APIs
Hoje vou revisar os recursos que foram incorporados com a introdução das Minimal APIs. |
As Minimal APIs ou APIs mínimas foram introduzidas no Preview 4 do .NET 6 e desde então foram habilitados um conjunto de recursos para melhorar e incrementar as Minimal APis. (Traduzido do original com alterações)
A seguir, fazendo uma revisão, veremos os principais recursos incorporados desde então.
1- Paridade com experiências existentes
As minimal APIs mudam fundamentalmente como o
código de inicialização do aplicativo é estruturado. Isso significa que algumas
das ferramentas e bibliotecas que enviamos que interagem com o aplicativo
precisam ser atualizadas para lidar com esse novo padrão. As seguintes
ferramentas e bibliotecas foram atualizadas em conformidade:
2- IResult para produzir respostas HTTP comuns
Na versões previews do .NET 6 anteriores, foram estendidas as implementações de IActionResult do MVC para oferecer suporte ao novo tipo IResult introduzido para APIs mínimas.
Agora, foram removidas as dependências entre IActionResult e IResult e foi adicionada uma nova classe de utilitário estática Results para produzir respostas HTTP comuns. Exemplo:
app.MapPut("/todos/{id}", async (TodoDbContext db, int id, Todo todo) =>
{
if (id != todo.Id)
{
return Results.BadRequest();
}
if (!await db.Todos.AnyAsync(x => x.Id == id))
{
return Results.NotFound();
}
db.Update(todo);
await db.SaveChangesAsync();
return Results.Ok();
});
|
3- Suporte a Request, Response e User para Actions
Foram adicionadas suporte para vincular os parâmetros HttpRequest, HttpResponse e ClaimsPrincipal em Actions.
Esses parâmetros
vêm das propriedades Request, Response e User em
HttpContext, respectivamente. Esta é uma adição ao suporte pré-existente para
vincular o HttpContext diretamente e também um
CancellationToken a partir de HttpContext.RequestAborted.
O exemplo abaixo aceita o usuário atual diretamente no método do manipulador de
solicitação.
app.MapGet("/api/items", async (ITodoService service, ClaimsPrincipal user) =>
{
return await service.GetListAsync(user.GetUserId());
})
.RequireAuthorization();
|
4- Melhorias no host e template
As APIs mínimas
introduziram novas APIs de hospedagem e, combinadas com novos recursos do C#
como Global using e instruções de nível superior, permitiram otimizar a
experiência de inicialização do aplicativo. Assim estes recursos foram
implementados nos outros modelos de projeto ASP.NET Core.
Por exemplo, ao criar uma nova ASP.NET Core Web API usando o template padrão,
você notará o seguinte:
Essas mudanças reduzem a quantidade de código padrão necessário para configurar e iniciar um novo aplicativo. Observe que o modelo de hospedagem existente e o padrão de inicialização continuarão a ser compatíveis com os aplicativos existentes.
5- Vinculação de parâmetro (Binding)
Na versão RC2, foi incluído o suporte em TryParse e BindAsync para métodos herdados. Também é verificado se existem métodos TryParse e BindAsync públicos que não estão no formato correto que gerarão um um erro para que você saiba que usou a sintaxe errada para seu(s) método (s).
Além disso, o método BindAsync agora tem outra sobrecarga com suporte que não requer o ParameterInfo:
public static ValueTask <T?> BindAsync(HttpContext
context)
Você pode adicionar um método TryParse estático em
seu tipo personalizado, conforme mostrado abaixo, se desejar vincular valores de
rota, atributos de cabeçalho e strings de consulta. O método
TryParse deve ter os seguintes formatos:
public static bool TryParse(string value, T out result);
public static bool TryParse(string value, IFormatProvider provider, T out result);
Abaixo um exemplo usando TryParse para um tipo complexo Point :
app.MapGet("/map", (Point point) => $"Point: {point.X}, {point.Y}");
public class Point public static bool TryParse(string? value, IFormatProvider? provider, out Point? point) point = null; |
O Request
/map?point=(10.1, 11.4) para o endpoint
acima retornará um objeto Point com os seguintes
valores de propriedade:
X = 10.1, Y = 11.4.
Além disso, se quiser assumir o controle do processo de vinculação para o seu
tipo, você pode usar as seguintes formas de BindAsync:
public static ValueTask<T?> BindAsync(HttpContext
context, ParameterInfo? parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
6- OpenAPI
Foram incluídas melhorias para permitir que você descreva se o corpo da solicitação é necessário ou não usando o método de extensão Accepts<TRequest>() ou o atributo [Consume (typeof (Todo), "application/json", IsRequired = false)].
O método de extensão Accepts e o atributo Consumes permitem que você expresse o tipo Todo e o contentType application/json para seus documentos open-api gerados, conforme indicado no exemplo abaixo.
app.MapPost("/todo", async (HttpRequest request) => { var todo = await request.Body.ReadAsJsonAsync<Todo>(); return todo is Todo ? Results.Ok(todo) : Results.Ok(); }) .Accepts<Todo>(isRequired: false, contentType: "application/json"); app.MapPost("/todo", HandlePostTodo);
|
Se desejar agrupar endpoints relacionados em coleções diferentes em documentos OpenAPI (Swagger), você pode fazer isso usando o método de extensão WithTags que permite fornecer os metadados de tags de agrupamento. Veja o exemplo de uso abaixo:
app.MapGet("/", () => "Hello World!")
.WithTags("Examples");
app.MapGet("/todos/sample", () => new[]
{
new Todo { Id = 1, Title = "Do this" },
new Todo { Id = 2, Title = "Do this too" }
})
.WithTags("Examples", "TodoApi");
|
Conclusão
Essas são algumas das novidades relacionadas com as Minimal APIs que foram introduzidas até agora no .NET 6. Como estamos na reta final do lançamento oficial acompanhe as novidades no blog oficial e registres suas experiências e problemas encontrados no GitHub.
"Porque todos devemos
comparecer ante o tribunal de Cristo, para que cada um receba segundo o que
tiver feito por meio do corpo, ou bem, ou mal."
2 Coríntios 5:10
Referências:
C# - Lendo e escrevendo em arquivos textos e binários
ASP .NET - Gerando QRCode com a API do Google
ASP .NET Core 2.1 - Como customizar o Identity
Usando o ASP .NET Core Identity - Macoratti
ASP .NET Core - Apresentando o IdentityServer4
ASP .NET Core 3.1 - Usando Identity de cabo a rabo