Escolha entre APIs baseadas em controlador e APIs mínimas

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

O ASP.NET Core dá suporte a duas abordagens para criar APIs: uma abordagem baseada em controlador e APIs mínimas. Os controladores em um projeto de API são classes que derivam de ControllerBase. APIs mínimas definem pontos de extremidade com manipuladores lógicos em lambdas ou métodos. Este artigo aponta diferenças entre as duas abordagens.

O design de APIs mínimas oculta a classe host por padrão e se concentra na configuração e extensibilidade por meio de métodos de extensão que assumem funções como expressões lambda. Os controladores são classes que podem assumir dependências por meio de injeção de construtor ou injeção de propriedade e geralmente seguem padrões orientados a objetos. APIs mínimas dão suporte à injeção de dependência por meio de outras abordagens, como o acesso ao provedor de serviços.

Aqui está o código de exemplo para uma API com base em controladores:


namespace APIWithControllers;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        builder.Services.AddControllers();
        var app = builder.Build();

        app.UseHttpsRedirection();

        app.MapControllers();

        app.Run();
    }
}
using Microsoft.AspNetCore.Mvc;

namespace APIWithControllers.Controllers;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

O código a seguir fornece a mesma funcionalidade em um projeto de API mínimo. Observe que a abordagem mínima da API envolve a inclusão do código relacionado em expressões lambda.


namespace MinimalAPI;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        var app = builder.Build();

        app.UseHttpsRedirection();

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

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

        app.Run();
    }
}

Ambos os projetos de API referem-se à seguinte classe:

namespace APIWithControllers;

public class WeatherForecast
{
    public DateOnly Date { get; set; }

    public int TemperatureC { get; set; }

    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

    public string? Summary { get; set; }
}

As APIs mínimas têm muitos dos mesmos recursos que as APIs baseadas em controlador. Elas dão suporte à configuração e à personalização necessárias para dimensionar para várias APIs, lidar com rotas complexas, aplicar regras de autorização e controlar o conteúdo das respostas à API. Há alguns recursos disponíveis com APIs baseadas em controlador que ainda não têm suporte ou são implementadas por APIs mínimas. Estão incluídos:

Confira também

O ASP.NET Core dá suporte a duas abordagens para criar APIs: uma abordagem baseada em controlador e APIs mínimas. Os controladores em um projeto de API são classes que derivam de ControllerBase. APIs mínimas definem pontos de extremidade com manipuladores lógicos em lambdas ou métodos. Este artigo aponta diferenças entre as duas abordagens.

O design de APIs mínimas oculta a classe host por padrão e se concentra na configuração e extensibilidade por meio de métodos de extensão que assumem funções como expressões lambda. Os controladores são classes que podem assumir dependências por meio de injeção de construtor ou injeção de propriedade e geralmente seguem padrões orientados a objetos. APIs mínimas dão suporte à injeção de dependência por meio de outras abordagens, como o acesso ao provedor de serviços.

Aqui está o código de exemplo para uma API com base em controladores:


namespace APIWithControllers;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        builder.Services.AddControllers();
        var app = builder.Build();

        app.UseHttpsRedirection();

        app.MapControllers();

        app.Run();
    }
}
using Microsoft.AspNetCore.Mvc;

namespace APIWithControllers.Controllers;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

O código a seguir fornece a mesma funcionalidade em um projeto de API mínimo. Observe que a abordagem mínima da API envolve a inclusão do código relacionado em expressões lambda.


namespace MinimalAPI;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        var app = builder.Build();

        app.UseHttpsRedirection();

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

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

        app.Run();
    }
}

Ambos os projetos de API referem-se à seguinte classe:

namespace APIWithControllers;

public class WeatherForecast
{
    public DateOnly Date { get; set; }

    public int TemperatureC { get; set; }

    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

    public string? Summary { get; set; }
}

As APIs mínimas têm muitos dos mesmos recursos que as APIs baseadas em controlador. Elas dão suporte à configuração e à personalização necessárias para dimensionar para várias APIs, lidar com rotas complexas, aplicar regras de autorização e controlar o conteúdo das respostas à API. Há alguns recursos disponíveis com APIs baseadas em controlador que ainda não têm suporte ou são implementadas por APIs mínimas. Estão incluídos:

  • Não há suporte interno para model binding (IModelBinderProvider, IModelBinder). O suporte pode ser adicionado com um shim de associação personalizado.
  • Não há suporte para associação de formulários. Isso inclui a associação IFormFile.
  • Não há suporte interno para validação (IModelValidator).
  • Não há suporte para partes do aplicativo ou para o modelo do aplicativo. Não há como aplicar ou criar suas próprias convenções.
  • Não há suporte nativo para renderização de exibição. É recomendável usar o RazorPages para renderizar exibições.
  • Não há suporte para JsonPatch
  • Não há suporte para OData

Confira também