Desde a configuração inicial do projeto usando a CLI do .NET até a configuração de middleware, controladores e serviços, aprenda cada etapa para criar uma API robusta. Descubra as práticas recomendadas para injeção de dependência, ações assíncronas e tratamento de exceções para criar aplicativos Web escalonáveis e eficientes.
1. Configurando um projeto de API da Web .NET 8
Conceito
Use a CLI do .NET para criar um novo projeto de API Web. Isso configura uma estrutura básica de projeto, incluindo Program.cs para inicialização e um controlador WeatherForecast como exemplo.
Exemplo de código
dotnet new webapi -n MyWebApi
2. Program.cs – Configuração mínima de API
Conceito
O .NET 8 continua a tendência de APIs mínimas, permitindo configurar serviços e endpoints de maneira simplificada e concisa diretamente no arquivo Program.cs.
Exemplo de código
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello, World!"); app.Run();
3. Definindo um Controlador
Conceito
Os controladores lidam com solicitações HTTP recebidas e respondem ao cliente. Eles são definidos herdando de ControllerBase e anotando com [ApiController].
Exemplo de código
[ApiController] [Route("[controller]")] public class MyController : ControllerBase { [HttpGet] public IActionResult Get() => Ok("Hello from MyController"); }
4. Injeção de dependência em controladores
Conceito
A injeção de dependência (DI) integrada do .NET Core facilita o gerenciamento de dependências. Você pode injetar serviços em seus controladores por meio de seus construtores.
Exemplo de código
public class MyService { public string GetMessage() => "Injected message"; } public class MyController : ControllerBase { private readonly MyService _myService; public MyController(MyService myService) { _myService = myService; } [HttpGet] public IActionResult Get() => Ok(_myService.GetMessage()); }
5. Configurando serviços
Conceito
Os serviços (como contextos de banco de dados, serviços personalizados, etc.) são configurados no arquivo Program.cs, tornando-os disponíveis para injeção de dependência em todo o seu aplicativo.
Exemplo de código
builder.Services.AddScoped<MyService>();
6. Configuração baseada no ambiente
Conceito
O .NET oferece suporte a arquivos de configuração específicos do ambiente (appsettings.json, appsettings.Development.json, etc.), permitindo diferentes configurações com base no ambiente do aplicativo.
Exemplo de código
// appsettings.Development.json { "Logging": { "LogLevel": { "Default": "Debug" } } }
7. Middleware
Conceito
Os componentes de middleware formam um pipeline que trata de solicitações e respostas. Middleware personalizado pode ser criado para questões transversais, como registro ou tratamento de erros.
Exemplo de código
app.Use(async (context, next) => { // Custom logic before passing to the next middleware await next(); // Custom logic after executing the next middleware });
8. Roteamento
Conceito
O roteamento na API Web .NET é obtido por meio do roteamento de atributos em controladores e métodos de ação. Isso permite que URLs sejam mapeados diretamente para ações do controlador.
Exemplo de código
[HttpGet("myaction/{id}")] public IActionResult GetAction(int id) => Ok($"Action with ID = {id}");
9. Vinculação de modelo
Conceito
A vinculação de modelo mapeia automaticamente dados de solicitações HTTP para parâmetros de método de ação. Ele oferece suporte a tipos complexos, incluindo corpos JSON e parâmetros de string de consulta.
Exemplo de código
public class MyModel { public int Id { get; set; } public string Name { get; set; } } [HttpPost] public IActionResult PostAction([FromBody] MyModel model) => Ok(model);
10. Validação de dados
Conceito
Anotações de dados podem ser usadas para validar dados do modelo. O atributo [ApiController] impõe automaticamente a validação, respondendo com 400 se o modelo for inválido.
Exemplo de código
public class MyModel { [Required] public int Id { get; set; } [StringLength(100)] public string Name { get; set; } }
11. Ações Assíncronas
Conceito
As ações assíncronas melhoram a escalabilidade, liberando threads enquanto aguardam a conclusão das operações de E/S. Use a palavra-chave async e retorne Task ou Task<IActionResult>.
Exemplo de código
[HttpGet("{id}")] public async Task<IActionResult> GetAsync(int id) { var result = await _service.GetByIdAsync(id); return Ok(result); }
12. Tratamento de exceções globalmente
Conceito
O tratamento global de exceções permite processamento centralizado de erros, registro e respostas de API padronizadas em exceções não tratadas.
Exemplo de código
app.UseExceptionHandler(a => a.Run(async context => { var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>(); var exception = exceptionHandlerPathFeature.Error; // Log the exception, generate a custom response, etc. context.Response.StatusCode = 500; await context.Response.WriteAsJsonAsync(new { Error = "An unexpected error occurred" }); }));
13. Versionamento de API
Conceito
O controle de versão da API ajuda a gerenciar alterações na API ao longo do tempo. A plataforma .NET oferece suporte ao controle de versão por meio de string de consulta, caminho de URL ou cabeçalho de solicitação.
Exemplo de código
builder.Services.AddApiVersioning(options => { options.AssumeDefaultVersionWhenUnspecified = true; options.DefaultApiVersion = new ApiVersion(1, 0); options.ReportApiVersions = true; });
14. Negociação de conteúdo
Conceito
A negociação de conteúdo permite que uma API atenda diferentes formatos de resposta com base no cabeçalho Accept da solicitação, permitindo suporte para formatos como JSON, XML, etc.
Exemplo de código
builder.Services.AddControllers() .AddXmlDataContractSerializerFormatters();
15. Configurações personalizadas de serialização JSON
Conceito
Personalize a formatação da resposta JSON, como nomenclatura camelCase ou ignorar valores nulos, definindo as configurações do serializador JSON.
Exemplo de código
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.IgnoreNullValues = true; });
16. Configurando CORS
Conceito
O Cross-Origin Resource Sharing (CORS) permite que sua API seja chamada de aplicativos da web hospedados em domínios diferentes. Configure a política CORS de acordo com seus requisitos.
Exemplo de código
builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => builder.WithOrigins("http://example.com")); }); app.UseCors("AllowSpecificOrigin");
17. Autenticação
Conceito
Proteja sua API habilitando a autenticação, que verifica a identidade dos usuários ou serviços que fazem solicitações.
Exemplo de código
builder.Services.AddAuthentication("Bearer") .AddJwtBearer(options => { options.Authority = "https://your-auth-server"; options.Audience = "your-api"; });
18. Autorização
Conceito
Após a autenticação, a autorização determina se um usuário autenticado tem permissão para executar uma ação ou acessar um recurso.
Exemplo de código
[Authorize] public class SecureController : ControllerBase { // Action methods here }
19. Integração Swagger/OpenAPI
Conceito
Swagger (OpenAPI) fornece documentação interativa para sua API, permitindo que os desenvolvedores a entendam e consumam facilmente.
Exemplo de código
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); app.UseSwagger(); app.UseSwaggerUI();
20. Registro
Conceito
O .NET Core fornece uma estrutura de log integrada que pode registrar mensagens em várias saídas (console, janela de depuração, serviços externos, etc.).
Exemplo de código
logger.LogInformation("This is an informational message"); app.Use(async (context, next) => { logger.LogError("This is an error message before the next middleware"); await next.Invoke(); // Log after calling the next middleware });
21. Usando o Entity Framework Core
Conceito
Entity Framework Core é um ORM usado para acesso a dados em aplicativos .NET. Ele permite consultar e manipular dados usando objetos fortemente tipados.
Exemplo de código
public class MyDbContext : DbContext { public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) {} public DbSet<MyModel> MyModels { get; set; } }
22. Migrações no Entity Framework Core
Conceito
As migrações permitem que você aplique controle de versão ao esquema do seu banco de dados rastreando alterações nos seus modelos de dados.
Exemplo de código
dotnet ef migrations add InitialCreate dotnet ef database update
23. Padrão de Repositório
Conceito
O padrão Repository abstrai a camada de dados, tornando seu aplicativo mais modular e mais fácil de manter.
Exemplo de código
public interface IRepository<T> { Task<IEnumerable<T>> GetAllAsync(); Task<T> GetByIdAsync(int id); // Other methods... } public class MyRepository<T> : IRepository<T> where T : class { private readonly MyDbContext _context; public MyRepository(MyDbContext context) { _context = context; } // Implement methods... }
24. Teste de Unidade
Conceito
O teste de unidade garante que sua API Web funcione corretamente, testando unidades individuais de código isoladamente.
Exemplo de código
public class MyControllerTests { [Fact] public async Task Get_ReturnsExpectedValue() { // Arrange var serviceMock = new Mock<IMyService>(); serviceMock.Setup(service => service.GetAsync()).ReturnsAsync("test"); var controller = new MyController(serviceMock.Object); // Act var result = await controller.Get(); // Assert Assert.Equal("test", result.Value); } }
25. Integração com Front-end
Conceito
A API da Web .NET pode servir como back-end para um aplicativo front-end, fornecendo serviços RESTful.
Exemplo de código
fetch('https://localhost:5001/mycontroller') .then(response => response.json()) .then(data => console.log(data));
26. Verificações de saúde
Conceito
As verificações de integridade fornecem uma maneira de monitorar o status do seu aplicativo e suas dependências, o que é útil para arquiteturas de microsserviços.
Exemplo de código
builder.Services.AddHealthChecks(); app.MapHealthChecks("/health");
27. Usando SignalR para comunicação em tempo real
Conceito
O SignalR permite funcionalidade web em tempo real, permitindo que o código do servidor envie notificações assíncronas para aplicativos web do lado do cliente.
Exemplo de código
public class MyHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } }
28. Configurando o cache de resposta
Conceito
O cache de resposta reduz o número de solicitações que um servidor deve atender, armazenando uma cópia dos recursos solicitados anteriormente.
Exemplo de código
[HttpGet("{id}")] [ResponseCache(Duration = 60)] public IActionResult GetById(int id) { // Retrieve and return your resource }
29. Arquivos estáticos
Conceito
Servir arquivos estáticos (HTML, CSS, JavaScript, etc.) é essencial para apoiar aplicativos front-end com uma API Web .NET.
Exemplo de código
app.UseStaticFiles(); // Enable static file serving
30. Configuração avançada e padrão de opções
Conceito
O padrão de opções usa classes para representar grupos de configurações relacionadas. Usando IOptions<T>, você pode acessar essas configurações em qualquer lugar do seu aplicativo.
Exemplo de código
public class MySettings { public string Setting1 { get; set; } // Other settings } builder.Services.Configure<MySettings>(builder.Configuration.GetSection("MySettings")); public class MyService { private readonly MySettings _settings; public MyService(IOptions<MySettings> settings) { _settings = settings.Value; } // Use _settings.Setting1 }
31. Middleware personalizado
Conceito
Middleware é um software montado em um pipeline de aplicativo para lidar com solicitações e respostas. Middleware personalizado pode ser criado para executar tarefas específicas.
Exemplo de código
public class MyCustomMiddleware { private readonly RequestDelegate _next; public MyCustomMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { // Pre-processing logic here await _next(httpContext); // Call the next middleware in the pipeline // Post-processing logic here } } // Extension method for easy middleware registration public static class MyCustomMiddlewareExtensions { public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware<MyCustomMiddleware>(); } }
32. Limitação de taxa
Conceito
A limitação de taxa protege sua API contra uso excessivo, limitando a frequência com que um usuário pode fazer solicitações dentro de um determinado período.
Exemplo de código
// Assume using a third-party library like AspNetCoreRateLimit builder.Services.AddInMemoryRateLimiting(); builder.Services.Configure<IpRateLimitOptions>(options => { options.GeneralRules = new List<RateLimitRule> { new RateLimitRule { Endpoint = "*", Limit = 100, Period = "1h" } }; });
33. Autenticação de chaves API
Conceito
As chaves de API são uma maneira simples de autenticar e autorizar chamadas de API. Eles são passados do cliente para o servidor na string de consulta ou no cabeçalho.
Exemplo de código
public class ApiKeyMiddleware { private readonly RequestDelegate _next; private const string APIKEYNAME = "x-api-key"; public ApiKeyMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { if (!context.Request.Headers.TryGetValue(APIKEYNAME, out var extractedApiKey)) { context.Response.StatusCode = 401; await context.Response.WriteAsync("API Key was not provided."); return; } // Validate the extracted API Key here... await _next(context); } }
34. Cache de saída
Conceito
O cache de saída permite armazenar a resposta a uma solicitação. As solicitações subsequentes podem ser atendidas a partir do cache, melhorando significativamente o desempenho.
Exemplo de código
[HttpGet] [ResponseCache(Duration = 120, Location = ResponseCacheLocation.Client, NoStore = false)] public IActionResult Get() { // Your logic here }
35. Tarefas em segundo plano
Conceito
As tarefas em segundo plano permitem que as operações sejam executadas em segundo plano, independentemente das solicitações do usuário, como o envio de e-mails ou o processamento de trabalhos de longa duração.
Exemplo de código
public class MyBackgroundService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // Your background task logic here await Task.Delay(TimeSpan.FromHours(1), stoppingToken); } } }
36. WebSockets
Conceito
WebSockets fornecem um canal de comunicação full-duplex em uma conexão única e de longa duração, ideal para aplicações em tempo real.
Exemplo de código
app.UseWebSockets(); app.Use(async (context, next) => { if (context.WebSockets.IsWebSocketRequest) { WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); // Handle the WebSocket request here } else { await next(); } });
37. Solicitar localização
Conceito
A localização de solicitações fornece uma maneira de localizar conteúdo para diferentes culturas e idiomas, com base nas informações da solicitação.
Exemplo de código
var supportedCultures = new[] { "en-US", "fr-FR" }; var localizationOptions = new RequestLocalizationOptions() .SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); app.UseRequestLocalization(localizationOptions);
38. Integrando com GraphQL
Conceito
GraphQL é uma linguagem de consulta para APIs. A integração de uma API Web .NET com GraphQL permite uma recuperação de dados mais eficiente.
Exemplo de código
// Assume using a library like HotChocolate builder.Services .AddGraphQLServer() .AddQueryType<Query>(); app.MapGraphQL();
39. Monitoramento e Telemetria
Conceito
O monitoramento e a telemetria envolvem coletar, analisar e agir com base em dados sobre o desempenho e o uso do seu aplicativo.
Exemplo de código
// Assume using Application Insights builder.Services.AddApplicationInsightsTelemetry("YOUR_INSTRUMENTATION_KEY");
40. Hubs SignalR e comunicação em tempo real
Conceito
SignalR é uma biblioteca que simplifica a adição de funcionalidades da web em tempo real aos aplicativos. A funcionalidade da Web em tempo real é a capacidade de fazer com que o código do servidor envie conteúdo para clientes conectados instantaneamente, sem exigir que o servidor espere que um cliente solicite novos dados. SignalR é perfeito para desenvolver aplicativos de chat, painéis em tempo real e aplicativos web mais interativos.
Exemplo de código
public class ChatHub : Hub { public async Task SendMessage(string user, string message) { // Call the broadcastMessage method to update clients. await Clients.All.SendAsync("broadcastMessage", user, message); } } // Startup or Program.cs app.MapHub<ChatHub>("/chathub");
Integração em Program.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // Other configurations... app.UseEndpoints(endpoints => { endpoints.MapHub<ChatHub>("/chathub"); }); }
41. Núcleo Avançado do Entity Framework – Relacionamentos
Conceito
O Entity Framework Core permite o mapeamento de relacionamentos complexos entre entidades, como um para um, um para muitos e muitos para muitos.
Exemplo de código
public class Author { public int AuthorId { get; set; } public string Name { get; set; } public ICollection<Book> Books { get; set; } } public class Book { public int BookId { get; set; } public string Title { get; set; } public int AuthorId { get; set; } public Author Author { get; set; } }
42. Atributos de validação personalizados
Conceito
Atributos de validação personalizados permitem definir sua lógica de validação para modelos de dados, estendendo os atributos de validação integrados.
Exemplo de código
public class MyCustomValidationAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // Your custom validation logic here if (value is int intValue && intValue > 0) { return ValidationResult.Success; } return new ValidationResult("Value must be positive"); } } public class MyModel { [MyCustomValidationAttribute] public int MyProperty { get; set; } }
43. Cenários de configuração avançada
Conceito
O padrão de opções do .NET oferece suporte a cenários de configuração complexos, incluindo objetos aninhados, listas e validação.
Exemplo de código
public class MyOptions { public MyNestedOptions Nested { get; set; } public List<string> Items { get; set; } } public class MyNestedOptions { public string Key { get; set; } } // In Program.cs or Startup.cs builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));
44. Monitoramento e perfil de desempenho
Conceito
O monitoramento e a criação de perfil de um aplicativo podem identificar gargalos e ineficiências, essenciais para otimizar o desempenho.
Exemplo de código
app.UseMiniProfiler();
45. Documentação API com comentários Swagger e XML
Conceito
Aprimore a documentação da sua API integrando comentários XML à interface do usuário do Swagger, proporcionando uma experiência mais rica para os desenvolvedores que consomem sua API.
Exemplo de código
builder.Services.AddSwaggerGen(c => { var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); });
46. Globalização e Localização
Conceito
A globalização e a localização permitem que seu aplicativo suporte vários idiomas e culturas, tornando-o acessível a um público global.
Exemplo de código
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
47. Cabeçalhos de segurança
Conceito
Melhorar a segurança do seu aplicativo da web adicionando vários cabeçalhos HTTP pode proteger contra ataques e vulnerabilidades comuns.
Exemplo de código
app.UseHsts(); app.UseXContentTypeOptions(); app.UseReferrerPolicy(opts => opts.NoReferrer()); app.UseXXssProtection(options => options.EnabledWithBlockMode()); app.UseXfo(options => options.Deny());
48. Sinalizadores de recursos
Conceito
Os sinalizadores de recursos permitem ativar e desativar recursos do seu aplicativo sem implantar novo código, facilitando testes e implementações.
Exemplo de código
// Using a library like Microsoft.FeatureManagement builder.Services.AddFeatureManagement();
49. Integração Blazor
Conceito
O Blazor permite que você crie UIs da web interativas usando C# em vez de JavaScript. A integração do Blazor com a API da Web fornece uma experiência de desenvolvimento full-stack perfeita.
Exemplo de código
// In a Blazor Server app @code { private IEnumerable<WeatherForecast> forecasts; protected override async Task OnInitializedAsync() { forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast"); } }
50. Middleware avançado para compactação de resposta
Conceito
A compactação de resposta pode reduzir o tamanho das respostas da API, melhorando os tempos de carregamento para clientes em redes lentas.
Exemplo de código
builder.Services.AddResponseCompression(options => { options.Providers.Add<GzipCompressionProvider>(); options.EnableForHttps = true; }); app.UseResponseCompression();
Programação C#🚀
Obrigado por fazer parte da comunidade C#! Antes que partas:
Se você chegou até aqui, mostre seu agradecimento com palmas e siga o autor! 👏️️
Siga-nos: X | LinkedIn | Dev.to | Hashnode | Boletim informativo | Tumblr
Visite nossas outras plataformas: GitHub | Instagram | TikTok | Quora | Diariamente.dev
Também publicado aqui