paint-brush
Como dominar a API da Web .NET 8: da configuração à segurança - as 50 melhores dicaspor@ssukhpinder
871 leituras
871 leituras

Como dominar a API da Web .NET 8: da configuração à segurança - as 50 melhores dicas

por Sukhpinder Singh22m2024/04/03
Read on Terminal Reader

Muito longo; Para ler

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.
featured image - Como dominar a API da Web .NET 8: da configuração à segurança - as 50 melhores dicas
Sukhpinder Singh HackerNoon profile picture
0-item
1-item
2-item
3-item
4-item

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