Novidades no .NET 6 e C# 10 – Minimal APIs

Este é o primeiro artigo de uma série focada nas novidades do .NET 6 e C# 10.

Eu sei que é difícil se manter atualizado com novas versões sendo lançadas, e que é frustrante se sentir desatualizado enquanto tanta coisa nova vem aparecendo.

Por essa razão decidi escrever esta série. Os artigos vão ser breves e objetivos.

Então, vamos lá?


Minimal APIs

Uma funcionalidade que, honestamente, me deixou bem animado foi a de desenvolver APIs de maneira minimalista. Talvez você já tenha notado, caso tenha escrito alguma API em Node.js, que dá para deixar mais simples a abordagem que geralmente utilizamos em .NET, utilizando Controllers e Actions, e montando toda sua estrutura.

No código abaixo, note como a API de WeatherForecast é definida. Na maneira tradicional, seu endpoint é definido na classe WeatherForecastController. Ao utilizar Minimal APIs, sua definição está no arquivo Program, com o código específico mostrado abaixo!

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
       new WeatherForecast
       (
           DateTime.Now.AddDays(index),
           Random.Shared.Next(-20, 55),
           summaries[Random.Shared.Next(summaries.Length)]
       ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

Vou mostrar agora o passo a passo para criar uma API e utilizar essa funcionalidade de Minimal APIs com .NET 6.


Passo a Passo

O primeiro passo, é iniciar a criação de um projeto API Web do ASP.NET Core. Após selecionar o modelo, e preencher informações como nome do projeto e solução, vai surgir a oportunidade de utilizar ou não Controllers. Neste momento, desmarque a opção, como é indicado no texto em parênteses, para utilizar Minimal APIs.

Criando projeto que não utilize Controllers

Prossiga e clique em Criar, e o projeto será… criado!

Neste momento talvez você leve um susto. Cadê a classe Startup e também a pasta Controllers? Bom, o que focamos aqui neste artigo será a ausência da pasta Controllers. Afinal, as rotas agora serão definidas no arquivo Program!

Para ter um exemplo nosso, vou apagar o código relacionado a esse endpoint no arquivo Program, e criar nosso próprio. O endpoint é acessado pelo método GET, no caminho /api/games. O arquivo Program vai ficar igual abaixo.

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.MapGet("/api/games", () =>
{
    var games = new List<Game>
    {
        new Game("Starcraft 2", "Estratégia"),
        new Game("Digimon World 3", "Jogo top."),
        new Game("Castlevania SOTN", "Outro jogo top.")
    };

    return Results.Ok(games);
})
.WithName("GetGames");

app.Run();

internal record Game(string Name, string Description)
{ }

Injeção de Dependência

Uma dúvida que possa surgir é a respeito de Injeção de Dependência. Como podemos fazer, nesse cenário? Para isso, basta utilizar os parâmetros do handler (que é onde efetivamente implementamos o retorno da API), como mostrado no código-fonte abaixo. Note que primeiro precisamos adicionar o objeto de tipo Config no contêiner de injeção de dependência, e então utilizá-lo através da anotação [FromServices] ao definir nossa Minimal API.

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<Config>(new Config("abcd"));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.MapGet("/api/games", ([FromServices] Config config) =>
{
    var games = new List<Game>
    {
        new Game("Starcraft 2", "Estratégia"),
        new Game("Digimon World 3", "Jogo top."),
        new Game("Castlevania SOTN", "Outro jogo top.")
    };

    return Results.Ok(games);
})
.WithName("GetGames");

app.Run();

internal record Game(string Name, string Description)
{ }

internal record Config(string Url)
{
}

O que achou? Curtiu essa novidade?


Conclusão

Foi abordado neste artigo a funcionalidade de Minimal APIs, introduzida com o lançamento do .NET 6.

Se curtiu a leitura, compartilha com os amigos e/ou nas redes sociais.