ASP.NET Core 7 - Novos Recursos
Neste artigo veremos os principais recursos adicionados na ASP.NET Core 7.0. |
1 - Cache de saída de Middleware
A ASP.NET Core 7 permite que você use o cache de saída em todos os aplicativos ASP.NET Core: Minimal API, MVC, Razor Pages e aplicativos Web API com controladores.
O recurso "Output Caching Middleware" que pode ser usado para implementar o cache de saída em um aplicativo web e o middleware de cache de saída permite que você armazene em cache a saída gerada por uma solicitação HTTP e a sirva diretamente do cache para solicitações subsequentes, melhorando assim o desempenho do aplicativo.
Para
adicionar o middleware de cache de saída à coleção de serviços,
invoque o método de extensão
IServiceCollection.AddOutputCache, e , para adicionar o
middleware ao pipeline de processamento de solicitação, chame o
método de extensão
IApplicationBuilder.UseOutputCache.
Em seguida, para adicionar uma camada de cache a um endpoint, você
pode usar o código a seguir.
var
builder = WebApplication.CreateBuilder(args); var app = builder.Build();app.MapGet( "/", () => "Olá Mundo!").CacheOutput();app.Run(); |
É importante destacar que :
2 - Middleware Rate-limiting
Controlar a taxa na qual os clientes podem fazer solicitações aos endpoints é uma importante medida de segurança que permite que os aplicativos da Web evitem ataques mal-intencionados. Você pode evitar ataques de negação de serviço, por exemplo, limitando o número de solicitações provenientes de um único endereço IP em um determinado período de tempo.
O middleware Microsoft.AspNetCore.RateLimiting na ASP.NET Core 7 pode ajudá-lo a impor a limitação de taxa em seu aplicativo. Você pode configurar políticas de limitação de taxa e, em seguida, anexar essas políticas aos endpoints, protegendo assim esses endpoints contra ataques de negação de serviço. Esse middleware é particularmente útil para aplicativos Web voltados para o público que são suscetíveis a esses ataques.
Você pode usar o middleware de limitação de taxa com aplicativos ASP.NET Core Web API, ASP.NET Core MVC e ASP.NET Core Minimal API. Para começar a usar esse middleware integrado, adicione o pacote NuGet Microsoft.AspNetCore.RateLimiting ao seu projeto executando o seguinte comando no prompt de comando do Visual Studio :
dotnet add package Microsoft.AspNetCore.RateLimiting
|
Pode também usar o comando a seguir na janela Package Manager Console:
Install-Package Microsoft.AspNetCore.RateLimiting
|
Após a instalação do middleware de limitação de taxa, inclua o trecho de código fornecido abaixo em seu arquivo Program.cs para adicionar serviços de limitação de taxa com a configuração padrão:
builder.Services.AddRateLimiter(options => { //código }); |
No exemplo a seguir usando a janela fixa de tempo e quantidade de requisições e a janela variável de tempo e quantidade requisições :
...
builder.Services.AddRateLimiter(_ => _
.AddFixedWindowLimiter("fixed", options =>
{
options.PermitLimit = 5;
options.Window = TimeSpan.FromSeconds(10);
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
options.QueueLimit = 2;
})
.AddSlidingWindowLimiter("sliding", options =>
{
options.PermitLimit = 5;
options.Window = TimeSpan.FromSeconds(10);
options.SegmentsPerWindow = 5;
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
options.QueueLimit = 2;
}));
var app = builder.Build();
app.UseRateLimiter();
...
|
Existem várias estratégias que podem ser usadas para implementar o rate limiting no ASP.NET Core. Algumas abordagens comuns incluem:
Para detalhes veja o vídeo a seguir : ASP.NET Core - Usando Rate Limiting
3 - Middleware de Descompactação de Request
A ASP.NET Core 7 inclui um novo middleware de descompactação de request que permite que os endpoints aceitem requests com conteúdo compactado. Isso elimina a necessidade de escrever código explicitamente para descompactar requests com conteúdo compactado.
A compactação de request é útil quando você deseja reduzir o tamanho dos dados transferidos entre o cliente e o servidor, especialmente em cenários onde a largura de banda é limitada ou quando você tem grandes volumes de dados sendo transmitidos. A compactação pode ajudar a melhorar o desempenho da aplicação, reduzir a latência e diminuir o consumo de largura de banda.
Este recurso funciona usando um cabeçalho HTTP de codificação de conteúdo para identificar e descompactar conteúdo compactado em requests HTTP. Em resposta a um request HTTP que corresponda ao valor do cabeçalho Content-Encoding, o middleware encapsula o HttpRequest.Body em um fluxo de descompactação adequado usando o provedor correspondente.
Isso é seguido pela remoção do cabeçalho Content-Encoding, que indica que o corpo da solicitação não está mais compactado. Observe que o middleware de descompactação ignora requests sem um cabeçalho Content-Encoding. Abaixo temos um trecho de código que mostra como você pode habilitar a descompactação de solicitação para os tipos padrão de codificação de conteúdo :
var
builder = WebApplication.CreateBuilder(args); builder.Services.AddRequestDecompression(); var app = builder.Build();app.UseRequestDecompression(); app.MapPost("/", (HttpRequest httpRequest) => Results.Stream(httpRequest.Body)); app.Run(); |
Os provedores de descompactação padrão são os formatos de compactação Brotli, Deflate e Gzip. Seus valores de cabeçalho de codificação de conteúdo são br, deflate e gzip, respectivamente.
4 - Filtros em APIs mínimas
Os filtros permitem que você execute o código durante determinados estágios no pipeline de processamento da solicitação. Um filtro é executado antes ou depois da execução de um método de ação e, você pode aproveitar os filtros para rastrear as visitas à página da web ou validar os parâmetros da solicitação.
Ao usar filtros,
você pode se concentrar na lógica de negócios de seu aplicativo, em vez de
escrever código para as preocupações transversais de seu aplicativo.
Um filtro de endpoint permite interceptar, modificar, curto-circuitar e agregar
problemas transversais, como autorização, validação e tratamento de exceções, e,
a nova interface IEndpointFilter no ASP.NET Core 7
nos permite projetar filtros e conectá-los aos endpoints da API.
Esses filtros podem alterar os objetos de solicitação ou resposta ou interromper o processamento da solicitação. Um filtro de endpoint pode ser invocado em ações e em endpoints de rota.
A interface IEndpointFilter é definida no namespace Microsoft.AspNetCore.Http conforme mostrado a seguir :
public
interface
IEndpointFilter { ValueTask<object?> InvokeAsync( EndpointFilterInvocationContext context, EndpointFilterDelegate next); } |
Aqui esta um exemplo de como criar um filtro de endpoint usando esta interface:
public
class
CustomEndpointFilter :
IEndpointFilter { public async Task OnExecutingAsync(HttpContext context, EndpointFilterContext filterContext) { // Lógica a ser executada antes do endpoint await Task.CompletedTask; } public async Task OnExecutedAsync(HttpContext context, EndpointFilterContext filterContext) { // Lógica a ser executada após o endpoint await Task.CompletedTask; } } |
No exemplo acima, a classe CustomEndpointFilter implementa a interface IEndpointFilter e define duas funções assíncronas: OnExecutingAsync e OnExecutedAsync. A função OnExecutingAsync é chamada antes da execução do endpoint, permitindo que você adicione lógica personalizada, como autenticação ou validação de solicitações. A função OnExecutedAsync é chamada após a execução do endpoint, permitindo que você adicione lógica de pós-processamento.
A seguir temos um trecho de código que ilustrar como múltiplos filtros de endpoints podem ser encadeados:
app.MapGet("/",
() => { return "Demonstrando filtros em múltiplos endpoints."; }) .AddEndpointFilter(async (endpointFilterInvocationContext, next) => { app.Logger.LogInformation("Primeiro filtro."); var result = await next(endpointFilterInvocationContext); return result; }) .AddEndpointFilter(async (endpointFilterInvocationContext, next) => { app.Logger.LogInformation("Segundo filtro."); var result = await next(endpointFilterInvocationContext); return result; }) .AddEndpointFilter(async (endpointFilterInvocationContext, next) => { app.Logger.LogInformation("Terceiro filtro."); var result = await next(endpointFilterInvocationContext); return result; }); |
Usando a nova interface IEndpointFilter, você pode adicionar lógica personalizada em pontos específicos do pipeline de processamento de endpoints, fornecendo uma maneira mais flexível de controlar o fluxo de execução e adicionar funcionalidades personalizadas às suas APIs mínimas na ASP.NET Core 7.0.
Veja também o meu artigo : NET 7 - Usando filtros em Mininal APIs
5- Associação de
parâmetros em métodos Action usando DI
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. Portanto,
se o tipo estiver configurado como um serviço, não será mais necessário
adicionar o atributo [FromServices] aos parâmetros
do seu método.
Antes da ASP.NET Core 7.0, era necessário usar as anotações [FromServices] ou [FromBody] nos parâmetros de ação para sinalizar ao framework como eles deveriam ser vinculados. Com a introdução do recurso de associação de parâmetros usando DI, você não precisa mais dessas anotações explicitamente.
Agora, você pode simplesmente declarar um parâmetro em um método de ação do controlador e o ASP.NET Core usará o mecanismo de DI para resolver e vincular automaticamente esse parâmetro, com base em sua configuração de DI.
Aqui está um exemplo de uso deste recurso :
public
class
MeuController
: ControllerBase { private readonly IMeuService _meuService; public MeuController(IMeuService meuService) { _meuService = meuService; } [HttpGet( "api/minhaAction")]public IActionResult MinhaAction(int id, string nome, MeuModel meuModel) { // Parâmetros id, name e myModel são automaticamente vinculados usando DI // Lógica do método de ação return Ok(); } } |
No exemplo acima, o método de ação MinhaAction tem três parâmetros: id, nome e meuModel. Esses parâmetros serão automaticamente resolvidos e vinculados usando o mecanismo de DI da ASP.NET Core 7.0, sem a necessidade de anotações adicionais.
A ASP.NET Core procurará implementações registradas para os tipos de parâmetro no contêiner de DI e os fornecerá automaticamente ao método de ação.
Esse recurso pode simplificar o código dos métodos Action, removendo a necessidade de anotações adicionais e melhorando a experiência de desenvolvimento.
6- Typed results nas APIs mínimas
O
recurso "Typed Results" nas Minimal APIs da
ASP.NET Core 7.0 refere-se a uma funcionalidade que facilita o retorno de
resultados tipados em métodos Action das APIs. Com esse recurso, você pode
retornar resultados de ação fortemente tipados sem a necessidade de usar
as classes ActionResult<T>, OkObjectResult,
NotFoundObjectResult, entre outras.
A ideia por trás do "Typed Results" é fornecer uma maneira mais simples e intuitiva de retornar resultados de ação com um tipo específico, permitindo que você se concentre no resultado real em vez de se preocupar com a criação de um objeto ActionResult ou ObjectResult.
A interface
IResult foi adicionada no .NET 6 para representar
valores retornados de APIs mínimas que não fazem uso do suporte implícito para
serialização JSON do objeto retornado. Deve-se observar aqui que a classe
Result estática é usada para criar vários objetos
IResult que representam diferentes tipos de
respostas, como definir um código de status de retorno ou redirecionar o usuário
para uma nova URL. No entanto, como os tipos do framework retornados desses
métodos eram privados, não era possível verificar o tipo correto de
IResult sendo retornado dos métodos Action durante
o teste de unidade.
Com o .NET 7, os tipos do framework que implementam a interface
IResult agora são públicos. Assim, podemos usar
asserções de tipo ao escrever nossos testes de unidade, conforme mostrado no
trecho de código abaixo.
[TestClass()] public class MyDemoApiTests { [TestMethod()] public void MapMinhaApiTest() { var result = _MinhaApi.GetAllData(); Assert.IsInstanceOfType(result, typeof(Ok<MeuModel[]>)); } } |
A seguir temos outro exemplo de uso do "Typed Results" :
var
builder = WebApplication.CreateBuilder(args); var app = builder.Build();app.MapGet( "/api/minhaaction", () =>{ return new MeuModel { Id = 1, Nome = "Exemplo" }; }); app.Run(); |
No exemplo acima, um método Action é mapeado para a rota "/api/minhaaction" usando o método MapGet.
Em vez de retornar explicitamente um objeto ActionResult ou ObjectResult, é possível retornar diretamente uma instância do tipo MeuModel pois a ASP.NET Core 7.0 é capaz de inferir o tipo do resultado e automaticamente convertê-lo em uma resposta HTTP apropriada.
Com o uso dos "Typed Results", o código fica mais simples e legível, eliminando a necessidade de criar explicitamente objetos ActionResult ou ObjectResult.
Essa funcionalidade é particularmente útil ao desenvolver APIs com as Minimal APIs, que visam oferecer uma experiência de desenvolvimento mais concisa e simplificada.
7- Grupos de roteamento em APIs mínimas
Com a ASP.NET Core 7, você pode aproveitar o novo método de extensão
MapGroup para organizar grupos de endpoints que
compartilham um prefixo comum em suas APIs mínimas. O método de extensão
MapGroup não apenas reduz o código repetitivo, mas
também facilita a personalização de grupos inteiros de endpoints.
Antes da ASP.NET Core 7.0, nas APIs minimalistas, todas as rotas eram definidas diretamente no escopo do objeto WebApplication. Isso poderia levar a um código desorganizado e difícil de ler quando havia várias rotas.
Com o recurso de "Route Groups", você pode agrupar rotas relacionadas em blocos lógicos usando o método Map em um objeto IEndpointRouteBuilder. Isso ajuda a melhorar a organização do código, tornando-o mais legível e fácil de manter.
O trecho de código a seguir ilustrar como o MapGroup pode ser usado:
app.MapGroup("/public/autors") .MapAutorsApi() .WithTags("Public"); |
O próximo trecho de código ilustra o uso do método de extensão MapAutorsApi :
public
static
class
MyRouteBuilder { public static RouteGroupBuilder MapAutorsApi(this RouteGroupBuilder group) { group.MapGet("/", GetAllAutores); group.MapGet("/{id}", GetAutor); group.MapPost("/", CreateAutor); group.MapPut("/{id}", UpdateAutor); group.MapDelete("/{id}", DeleteAutor); return group; } } |
A seguir temos outro exemplo do uso do recurso "Route Groups" :
var
builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Map( "/api", api =>{ api.MapGet("/users", () => { // Lógica do endpoint /api/users }); api.MapPost( "/users", () =>{ // Lógica do endpoint /api/users }); api.MapGet( "/products", () =>{ // Lógica do endpoint /api/products }); // Outros endpoints do grupo /api }); app.Run(); |
No exemplo acima, as rotas relacionadas a usuários e produtos são agrupadas dentro do bloco /api usando o método Map. Dentro de cada bloco, você pode definir as rotas específicas relacionadas a esse grupo.
Ao agrupar as rotas relacionadas, você melhora a legibilidade do código e facilita a manutenção. Além disso, é possível aplicar filtros ou políticas de autenticação e autorização para um grupo inteiro de rotas, em vez de defini-los individualmente para cada rota.
O recurso de "Route Groups" é uma adição valiosa às Minimal APIs da ASP.NET Core 7.0, permitindo que você organize e estruture o código de forma mais clara e concisa, tornando o desenvolvimento e a manutenção de APIs mais eficientes.
8 - Uploads de arquivos em APIs mínimas
Anteriormente, nas versões anteriores da ASP.NET Core, o suporte a upload de arquivos exigia configurações adicionais e manipulação manual dos dados do arquivo.
Com a ASP.NET Core 7.0, o suporte a upload de arquivos é simplificado nas Minimal APIs, permitindo que você lide facilmente com o recebimento de arquivos enviados por meio de uma requisição HTTP.
Agora você pode usar IFormFile e IFormFileCollection em APIs mínimas para carregar arquivos na ASP.NET Core 7. O trecho de código a seguir ilustra como IFormFile pode ser usado.
var
builder = WebApplication.CreateBuilder(args); var app = builder.Build();app.MapPost( "/uploadfile", async (IFormFile iformFile) =>{ var tempFileName = Path.GetTempFileName(); using var fileStream = File.OpenWrite(tempFileName); await iformFile.CopyToAsync(fileStream); }); app.Run(); |
Se você deseja carregar vários arquivos, pode usar o seguinte trecho de código :
var
builder = WebApplication.CreateBuilder(args); var app = builder.Build();app.MapPost( "/uploadfiles", async (IFormFileCollection files) =>{ foreach (var file in files) { var tempFileName = Path.GetTempFileName(); using var fileStream = File.OpenWrite(tempFileName); await file.CopyToAsync(fileStream); } }); app.Run(); |
A ASP.NET Core 7.0 lida automaticamente com o recebimento do arquivo na requisição HTTP e converte-o em um objeto IFormFile para que você possa manipulá-lo facilmente no código do método de ação.
Com esse recurso, o processo de upload de arquivos em APIs minimalistas é simplificado, permitindo que você se concentre na lógica de processamento do arquivo, sem a necessidade de lidar manualmente com a extração e manipulação dos dados do arquivo.
Para mais detalhes veja o meu artigo: NET 7 - Mininal APIs : Upload de arquivos
9- Health checks para gRPC
A ASP.NET Core oferece suporte ao uso do middleware Health Checks para relatar a integridade dos componentes da infraestrutura do seu aplicativo.
As verificações de integridade são uma parte essencial do monitoramento e operação de sistemas distribuídos. Elas permitem que você verifique se seus serviços estão funcionando corretamente e estejam disponíveis para lidar com solicitações.
Agora a ASP.NET
Core 7 adiciona suporte integrado para monitorar a integridade dos serviços gRPC
por meio do pacote nuget Grpc.AspNetCore.HealthChecks.
Você pode usar este pacote para expor um endpoint em seu aplicativo gRPC que
permite verificações de integridade.
Observe que você normalmente usaria verificações de integridade com um sistema
de monitoramento externo ou com um balanceador de carga ou orquestrador de
contêiner. O último pode automatizar uma ação, como reiniciar ou redirecionar o
serviço com base no status de integridade.
Com esse novo recurso, você pode definir verificações de integridade específicas para seus serviços gRPC e expor um endpoint dedicado para verificar o status de saúde do serviço.
Aqui está um exemplo de como usar o recurso:
var
builder = WebApplication.CreateBuilder(args); // ... // Adiciona suporte a health checks para serviços gRPC builder.Services.AddGrpcHealthChecks(); var app = builder.Build();// ... app.UseEndpoints(endpoints => { // Mapeia o endpoint de health checks para serviços gRPC endpoints.MapGrpcHealthChecks("/health"); // Mapeia o serviço gRPC endpoints.MapGrpcService<MeuGrpcService>(); }); app.Run(); |
No exemplo acima, estamos adicionando o suporte a verificações de integridade para serviços gRPC usando AddGrpcHealthChecks e, em seguida, mapeando um endpoint "/health" para as verificações de integridade do serviço gRPC usando MapGrpcHealthChecks. Além disso, estamos mapeando um serviço gRPC chamado MeuGrpcService usando MapGrpcService.
Essas linhas de código permitem que você exponha um endpoint "/health" que pode ser usado para verificar o status de saúde do serviço gRPC. Você pode personalizar as verificações de integridade de acordo com as necessidades do seu serviço gRPC, adicionando lógica personalizada para verificar componentes, conexões de banco de dados, serviços externos, etc.
Com este recurso, você pode ter um controle mais abrangente sobre a saúde dos seus serviços gRPC e garantir que eles estejam operacionais e prontos para lidar com as solicitações dos clientes. Isso contribui para a confiabilidade e estabilidade do seu sistema distribuído.
Temos assim nove recursos importantes que foram adicionados a ASP.NET Core na versão 7.0 que vão incrementar o desenvolvimento web em diversos aspectos.
E estamos conversados ...
"E não vos
embriagueis com vinho, em que há contenda, mas enchei-vos do Espírito;
Falando entre vós em salmos, e hinos, e cânticos espirituais; cantando e
salmodiando ao Senhor no vosso coração;"
Efésios 5:18,19
Referências: