Sviluppo API REST con ASP.NET Core
Sviluppo API REST con ASP.NET Core
Introduzione
Lo sviluppo di API RESTful rappresenta oggi una competenza fondamentale per ogni ingegnere informatico e sviluppatore .NET. ASP.NET Core offre un framework moderno, performante e cross-platform per la creazione di servizi web scalabili e manutenibili. In questa guida tecnica esploreremo le Minimal API, un approccio semplificato e leggero introdotto a partire da .NET 6, che permette di costruire API RESTful con codice minimo e massima leggibilità.
L’obiettivo di questo articolo è fornire una guida pratica per sviluppare API REST moderne, estensibili e ben organizzate, partendo dalle Minimal API fino ad arrivare alle best practices architetturali per progetti di livello enterprise.
1. Introduzione allo Sviluppo API REST con ASP.NET Core
ASP.NET Core rappresenta un’evoluzione significativa del framework .NET, offrendo un’architettura modulare, prestazioni elevate e supporto nativo per lo sviluppo cloud-native. Per lo sviluppo di API HTTP, ASP.NET Core mette a disposizione due approcci principali: le API basate su controller (Controller-based APIs) e le Minimal API.
Le Minimal API, raccomandate da Microsoft per i nuovi progetti, rappresentano un paradigma semplificato che elimina la complessità della pipeline MVC tradizionale. Questo approccio riduce significativamente il boilerplate code e permette di esprimere la logica dell’applicazione in modo più diretto e leggibile. Le performance ne beneficiano enormemente, poiché la pipeline di elaborazione delle richieste risulta più snella rispetto all’approccio MVC.
Le Minimal API sono particolarmente adatte per microservizi, prototipazione rapida e applicazioni che non richiedono le funzionalità avanzate del pattern MVC, come i model binder personalizzati o i filtri complessi. Tuttavia, questo non significa che siano limitate: supportano dependency injection, middleware, validazione, autenticazione e tutte le funzionalità necessarie per costruire API production-ready.
2. Minimal API: Setup, Routing, Binding e Middleware
Setup Iniziale
Creare una Minimal API è estremamente semplice. Ecco un esempio base:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Questo codice crea un’API completa e funzionante. La fase di builder configura i servizi, mentre la fase di app configura la pipeline HTTP e definisce gli endpoint.
Routing e Verbi HTTP
Il routing nelle Minimal API è dichiarativo e intuitivo. Gli endpoint si definiscono utilizzando i metodi MapGet, MapPost, MapPut, MapDelete:
app.MapGet("/products", () => Results.Ok(GetAllProducts()));
app.MapGet("/products/{id}", (int id) => Results.Ok(GetProduct(id)));
app.MapPost("/products", (Product product) => Results.Created($"/products/{product.Id}", product));
app.MapPut("/products/{id}", (int id, Product product) => Results.NoContent());
app.MapDelete("/products/{id}", (int id) => Results.NoContent());
Parameter Binding
Il parameter binding avviene automaticamente. ASP.NET Core determina la sorgente dei parametri basandosi sul contesto:
app.MapGet("/api/search", (string query, int page, [FromHeader] string apiKey) =>
{
// query e page vengono dalla query string
// apiKey viene dall'header HTTP
return Results.Ok(new { query, page, apiKey });
});
Per i tipi complessi, il binding avviene dal body della richiesta:
app.MapPost("/api/orders", (Order order) =>
{
// Order viene deserializzato dal body JSON
return Results.Created($"/api/orders/{order.Id}", order);
});
Middleware
I middleware possono essere aggiunti nella pipeline per gestire aspetti trasversali come logging, autenticazione, gestione errori:
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
3. Organizzazione Modulare – Sviluppo API REST con ASP.NET Core
Anche se le Minimal API possono risiedere in un singolo file, per progetti di dimensioni realistiche è fondamentale adottare un’organizzazione modulare. L’approccio consigliato prevede la separazione degli endpoint in classi dedicate:
// ProductEndpoints.cs
public static class ProductEndpoints
{
public static void MapProductEndpoints(this WebApplication app)
{
var group = app.MapGroup("/api/products");
group.MapGet("/", GetAll);
group.MapGet("/{id}", GetById);
group.MapPost("/", Create);
}
private static IResult GetAll(IProductService service)
=> Results.Ok(service.GetAll());
private static IResult GetById(int id, IProductService service)
=> Results.Ok(service.GetById(id));
}
Nel file Program.cs si registrano poi gli endpoint in modo ordinato:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProductServices();
var app = builder.Build();
app.MapProductEndpoints();
app.Run();
Questa organizzazione mantiene il Program.cs pulito e facilita la manutenzione del codice, consentendo di scalare l’applicazione mantenendo una struttura chiara.
4. JSON e Serializzazione con System.Text.Json – Sviluppo API REST con ASP.NET Core
ASP.NET Core utilizza System.Text.Json come serializzatore JSON predefinito. Questo componente offre prestazioni superiori rispetto a Json.NET (Newtonsoft.Json) ed è ottimizzato per scenari moderni.
La configurazione della serializzazione JSON avviene tramite JsonSerializerOptions:
builder.Services.Configure<JsonOptions>(options =>
{
options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.SerializerOptions.WriteIndented = true;
options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});
System.Text.Json gestisce automaticamente la serializzazione di tipi comuni come stringhe, numeri, date, collezioni e oggetti complessi. Per le date, il formato predefinito è ISO 8601, che garantisce interoperabilità e compatibilità internazionale.
5. Naming Policy e Converter Personalizzati – Sviluppo API REST con ASP.NET Core
Naming Policy
Le naming policy permettono di convertire automaticamente i nomi delle proprietà C# (tipicamente PascalCase) nel formato desiderato per il JSON (tipicamente camelCase):
options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
È possibile creare naming policy personalizzate estendendo la classe JsonNamingPolicy:
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
if (string.IsNullOrEmpty(name)) return name;
var builder = new StringBuilder();
builder.Append(char.ToLower(name[0]));
for (int i = 1; i < name.Length; i++)
{
if (char.IsUpper(name[i]))
{
builder.Append('_');
builder.Append(char.ToLower(name[i]));
}
else builder.Append(name[i]);
}
return builder.ToString();
}
}
Converter Personalizzati
Per gestire tipi personalizzati o formati specifici, è possibile implementare converter custom ereditando da JsonConverter<T>:
public class DateOnlyConverter : JsonConverter<DateOnly>
{
public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> DateOnly.Parse(reader.GetString()!);
public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
=> writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
}
Il converter si registra nelle opzioni di serializzazione:
options.SerializerOptions.Converters.Add(new DateOnlyConverter());
6. Swagger e OpenAPI
Swagger, basato sulla specifica OpenAPI, è lo standard de facto per la documentazione delle API REST. Permette di generare automaticamente documentazione interattiva e testabile direttamente dal codice.
Setup di Swagger
Per integrare Swagger in un progetto ASP.NET Core, è necessario installare il pacchetto Swashbuckle.AspNetCore e configurarlo:
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Product API",
Description = "API per la gestione dei prodotti",
Contact = new OpenApiContact
{
Name = "Team Sviluppo",
Email = "info@example.com"
}
});
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Product API V1");
c.RoutePrefix = string.Empty; // Swagger alla root
});
}
Questa configurazione espone la documentazione Swagger UI all’indirizzo root dell’applicazione quando eseguita in ambiente di sviluppo.
7. Documentazione Automatica – Sviluppo API REST con ASP.NET Core
La documentazione automatica si ottiene arricchendo il codice con attributi e commenti XML. Per le Minimal API, è possibile utilizzare metodi di estensione per aggiungere metadati:
app.MapGet("/api/products/{id}", (int id) => Results.Ok())
.WithName("GetProduct")
.WithTags("Products")
.Produces<Product>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
Per abilitare i commenti XML, configurare il file .csproj:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
E configurare Swagger per leggerli:
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory,
$"{Assembly.GetExecutingAssembly().GetName().Name}.xml"));
La documentazione risultante include descrizioni, tipi di risposta, codici di stato HTTP e schemi dei modelli, rendendo l’API facilmente comprensibile e integrabile da parte dei consumatori.
8. Best Practices Architetturali per API
Un’architettura ben progettata è fondamentale per la manutenibilità e scalabilità di un’API. Ecco alcune best practices consolidate:
Dependency Injection
Utilizzare sempre la dependency injection per gestire le dipendenze tra componenti:
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddScoped<IProductRepository, ProductRepository>();
Gestione degli Errori
Implementare una gestione centralizzata degli errori tramite middleware personalizzato o l’integrazione di ProblemDetails:
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
context.Response.ContentType = "application/json";
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError,
Title = "Internal Server Error",
Detail = "Si è verificato un errore imprevisto"
};
await context.Response.WriteAsJsonAsync(problemDetails);
});
});
Validazione
Implementare validazione robusta utilizzando Data Annotations o FluentValidation:
public record CreateProductRequest(
[Required][MaxLength(100)] string Name,
[Range(0.01, double.MaxValue)] decimal Price
);
Versionamento
Prevedere fin da subito un meccanismo di versionamento dell’API:
var v1 = app.MapGroup("/api/v1");
v1.MapProductEndpoints();
var v2 = app.MapGroup("/api/v2");
v2.MapProductEndpointsV2();
9. Separazione tra Layer: DTO, Servizi e Modelli – Sviluppo API REST con ASP.NET Core
La separazione dei layer è un principio architetturale fondamentale che previene l’accoppiamento stretto tra componenti e facilita la manutenzione.
Modelli di Dominio
I modelli di dominio rappresentano le entità del sistema e contengono la logica di business:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public DateTime CreatedAt { get; set; }
public bool IsActive { get; set; }
}
Data Transfer Objects (DTO)
I DTO sono oggetti leggeri utilizzati per trasferire dati tra layer e verso l’esterno dell’applicazione:
public record ProductDto(int Id, string Name, decimal Price);
public record CreateProductDto(string Name, decimal Price);
public record UpdateProductDto(string Name, decimal Price);
I DTO offrono numerosi vantaggi: disaccoppiano la struttura interna dall’interfaccia pubblica, prevengono problemi di serializzazione circolare, permettono di esporre solo i dati necessari migliorando la sicurezza e le prestazioni.
Layer di Servizio
Il layer di servizio contiene la logica di business e orchestra le operazioni tra repository e controller:
public interface IProductService
{
Task<IEnumerable<ProductDto>> GetAllAsync();
Task<ProductDto?> GetByIdAsync(int id);
Task<ProductDto> CreateAsync(CreateProductDto dto);
}
public class ProductService : IProductService
{
private readonly IProductRepository _repository;
private readonly IMapper _mapper;
public ProductService(IProductRepository repository, IMapper mapper)
{
_repository = repository;
_mapper = mapper;
}
public async Task<IEnumerable<ProductDto>> GetAllAsync()
{
var products = await _repository.GetAllAsync();
return _mapper.Map<IEnumerable<ProductDto>>(products);
}
}
Repository Pattern
Il repository pattern astrae l’accesso ai dati:
public interface IProductRepository
{
Task<IEnumerable<Product>> GetAllAsync();
Task<Product?> GetByIdAsync(int id);
Task<Product> CreateAsync(Product product);
}
Questa separazione garantisce che modifiche al database o alla logica di business non impattino sull’interfaccia pubblica dell’API.
10. AutoMapper: Cenni – Sviluppo API REST con ASP.NET Core
AutoMapper è una libreria che automatizza il mapping tra oggetti di tipi diversi, eliminando il codice ripetitivo di conversione tra modelli e DTO.
Configurazione
AutoMapper si configura definendo profili di mapping:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Product, ProductDto>();
CreateMap<CreateProductDto, Product>();
CreateMap<UpdateProductDto, Product>();
}
}
Registrazione
Si registra nei servizi dell’applicazione:
builder.Services.AddAutoMapper(typeof(Program).Assembly);
Utilizzo
Una volta configurato, si utilizza tramite dependency injection:
public class ProductService
{
private readonly IMapper _mapper;
public ProductService(IMapper mapper) => _mapper = mapper;
public ProductDto Convert(Product product)
=> _mapper.Map<ProductDto>(product);
}
AutoMapper riduce significativamente il boilerplate code, facilita la manutenzione e rende il codice più leggibile, permettendo agli sviluppatori di concentrarsi sulla logica di business piuttosto che sulla conversione manuale degli oggetti.
Conclusioni e Formazione Continua – Sviluppo API REST con ASP.NET Core
Lo Sviluppo API REST con ASP.NET Core richiede una solida comprensione dei principi architetturali, delle best practices e degli strumenti moderni del framework. Le Minimal API rappresentano un’evoluzione significativa che semplifica lo sviluppo senza sacrificare potenza e flessibilità.
Tuttavia, la tecnologia evolve rapidamente e le sfide dei progetti enterprise richiedono aggiornamento costante. La formazione continua del team di sviluppo è essenziale per affrontare con successo le complessità dei progetti lavorativi e per supportare efficacemente il lavoro quotidiano delle persone che utilizzano i sistemi che sviluppiamo.
Per questo motivo, è fondamentale investire in percorsi formativi strutturati e aggiornati. Innovaformazione.net offre corsi specializzati su ASP.NET Core e sul mondo dei microservizi .NET, con modalità flessibili che includono sia online in classe virtuale che frontale in presenza.
I corsi sono progettati specificamente per sviluppatori professionisti, ingegneri informatici e laureati in informatica che desiderano approfondire le competenze su architetture moderne, pattern avanzati e best practices enterprise. Puoi esplorare l’offerta formativa completa nell’ambito .NET al seguente link: https://innovaformazione.net/categorie-corsi/microsoft-net/
In particolare, il Corso ASP.NET Core fornisce una formazione approfondita su tutti gli aspetti trattati in questo articolo e molto altro, con esercitazioni pratiche e casi d’uso reali.
Un aspetto importante da considerare è la possibilità di finanziare la formazione aziendale attraverso Fondimpresa o altri fondi interprofessionali. Innovaformazione può gestire l’intero progetto di formazione finanziata, occupandosi di tutti gli aspetti burocratici e organizzativi, permettendo alle aziende di formare i propri team senza impatti economici significativi. Maggiori informazioni sulla formazione finanziata sono disponibili QUI.
Investire nella formazione del team significa investire nella qualità del software, nella produttività e nella capacità di affrontare con successo le sfide tecnologiche del futuro.
Contatti – formazione Sviluppo API REST con ASP.NET Core
Per informazioni sui corsi e sulla formazione aziendale:
Email: info@innovaformazione.net
Tel: 3471012275 (Dario Carrassi)
(fonte) (fonte) (fonte) (fonte)
Per altri articoli tecnici consigliamo di navigare sul nostro blog QUI.
Vuoi essere ricontattato? Lasciaci il tuo numero telefonico e la tua email, ti richiameremo nelle 24h:
Articoli correlati
Guida SAP Clean ABAP
Lavoro Contabilità Bilancio Roma
Come integrare l’AI negli ATM bancomat
Guida Android XR SDK
Lavoro Logistica Supply Piemonte
